在UE4上进行TCP Server的创建与通讯

在UE4上进行TCP Server的创建与通讯

简介

UE4 版本 : 4.20.3
Visual Studio 版本:2017

在UE4上创建TCP Server并监听客户端接入建立通讯
建立通讯后进行双向数据传输

先决条件

在xxx.Build.cs 文件中添加以下部分
“Sockets”, “Networking”
修改后:

// Fill out your copyright notice in the Description page of Project Settings.

using UnrealBuildTool;

public class AVR_Server : ModuleRules
{
	public AVR_Server(ReadOnlyTargetRules Target) : base(Target)
	{
		PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
	
		PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "Sockets", "Networking" });

		PrivateDependencyModuleNames.AddRange(new string[] {  });

		// Uncomment if you are using Slate UI
		// PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" });
		
		// Uncomment if you are using online features
		// PrivateDependencyModuleNames.Add("OnlineSubsystem");

		// To include OnlineSubsystemSteam, add it to the plugins section in your uproject file with the Enabled attribute set to true
	}
}

代码

首先创建BlueprintFunctionLibrary名为TCPSocketServer

H文件

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "Runtime/Networking/Public/Networking.h"
#include "Engine.h"
#include "TCPSocketServer.generated.h"

/**
 * 
 */
UCLASS()
class AVR_SERVER_API UTCPSocketServer : public UBlueprintFunctionLibrary
{
	GENERATED_BODY()
public:
	UFUNCTION(BlueprintCallable, Category = "MySocket")
		static bool createSoc();
	UFUNCTION(BlueprintCallable, Category = "MySocket")
		static void closeSoc();
	UFUNCTION(BlueprintCallable, Category = "MySocket")
		static bool bindSoc(const FString& TheIP, const int32 ThePort);
	UFUNCTION(BlueprintCallable, Category = "MySocket")
		static bool listenSoc(const int32 MaxBacklog);
	UFUNCTION(BlueprintCallable, Category = "MySocket")
		static bool acceptSoc(FString& TheIP,int32 & ThePort);
	UFUNCTION(BlueprintCallable, Category = "MySocket")
		static bool sendSoc(const FString& sendMessage);
	UFUNCTION(BlueprintCallable, Category = "MySocket")
		static FString recvSoc();
	static FString StringFromBinaryArray(const TArray<uint8>& BinaryArray);

};

C文件

// Fill out your copyright notice in the Description page of Project Settings.

#include "TCPSocketServer.h"


FSocket* SocketServer;
FSocket* SocketClient;
FIPv4Address ip;



void UTCPSocketServer::closeSoc()
{
	if (SocketServer)
	{
		//关闭,销毁
		SocketServer->Close();
		ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->DestroySocket(SocketServer);
	}
	if (SocketClient)
	{
		//关闭,销毁
		SocketClient->Close();
		ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->DestroySocket(SocketClient);
	}
}

bool UTCPSocketServer::createSoc()
{
	SocketServer = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateSocket(NAME_Stream, TEXT("default"), false);

	if (!SocketServer) {
		return false;
	}
	// SocketServer.SetNonBlocking(false);
	//SocketServer->SetNonBlocking(false);
	return true;
}

bool UTCPSocketServer::bindSoc(const FString & TheIP, const int32 ThePort)
{
	FIPv4Address::Parse(TheIP, ip);
	TSharedRef<FInternetAddr> addr = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateInternetAddr();
	addr->SetIp(ip.Value);
	addr->SetPort(ThePort);
	bool bBind = SocketServer->Bind(*addr);
	return bBind;
}

bool UTCPSocketServer::listenSoc(const int32 MaxBacklog)
{
	bool bListen = SocketServer->Listen(MaxBacklog);
	return bListen;
}

bool UTCPSocketServer::acceptSoc(FString & TheIP,int32 & ThePort)
{
	TSharedRef<FInternetAddr> targetAddr = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateInternetAddr();
	FIPv4Address::Parse(TheIP, ip);
	uint32 ipd;
	//targetAddr->SetIp(ip.Value);
	//targetAddr->SetPort(ThePort);
	SocketClient = SocketServer->Accept(*targetAddr, "aaa");
	ThePort = targetAddr->GetPort();
	targetAddr->GetIp(ipd);
	


	char strTemp[20];
	sprintf(strTemp, "%d.%d.%d.%d",
		(ipd & 0xff000000) >> 24,
		(ipd & 0x00ff0000) >> 16,
		(ipd & 0x0000ff00) >> 8,
		(ipd & 0x000000ff));


	TheIP = FString(strTemp);


	if (!SocketClient)
		return false;
	return true;
}

bool UTCPSocketServer::sendSoc(const FString & sendMessage)
{
	TSharedRef<FInternetAddr> targetAddr = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateInternetAddr();
	//FIPv4Address::Parse(TheIP, ip);
	//targetAddr->SetIp(ip.Value);
	//targetAddr->SetPort(ThePort);

	FString serialized = sendMessage;

	bool bsend;
	TCHAR *seriallizedChar = serialized.GetCharArray().GetData();
	int32 size = FCString::Strlen(seriallizedChar) + 1;
	int32 sent = 0;
	//注意,要用客户端这个socket
	bsend = SocketClient->SendTo((uint8*)TCHAR_TO_UTF8(seriallizedChar), size, sent, *targetAddr);

	if (bsend)
	{
		GEngine->AddOnScreenDebugMessage(1, 2.0f, FColor::Green, TEXT("_____Send Succ!"));
		UE_LOG(LogTemp, Warning, TEXT("_____Send Succ!"));
	}
	else
	{
		GEngine->AddOnScreenDebugMessage(1, 2.0f, FColor::Green, TEXT("_____Send failed!"));
		UE_LOG(LogTemp, Warning, TEXT("_____Send failed!"));
	}
	return bsend;
}

FString UTCPSocketServer::recvSoc()
{
	TSharedRef<FInternetAddr> targetAddr = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateInternetAddr();
	TArray<uint8> ReceivedData;//定义一个接收器
	uint32 Size;
	//注意,要用客户端这个socket
	if (SocketClient->HasPendingData(Size))
	{
		uint8 *Recv = new uint8[Size];
		int32 BytesRead = 0;
		//将数组调整到给定数量的元素。 新元素将被初始化。
		ReceivedData.SetNumUninitialized(FMath::Min(Size, 65507u));
		//注意,要用客户端这个socket
		SocketClient->RecvFrom(ReceivedData.GetData(), ReceivedData.Num(), BytesRead, *targetAddr);
		if (ReceivedData.Num() > 0)
		{
			//打印
			//GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("Data Bytes Read ~> %d"), ReceivedData.Num()));
			FString ReceivedUE4String = StringFromBinaryArray(ReceivedData);
			return ReceivedUE4String;
			//GEngine->AddOnScreenDebugMessage(-1, 0.5f, FColor::Red, FString::Printf(TEXT("As String Data ~> %s"), *ReceivedUE4String));
			//判断是否发送了相对的指令,进行对应事件调用
			//if (ReceivedUE4String.Equals("jiegege"))
			//{
			//	sendSoc("server auto send ");
			//}



		}
	}
	return FString();
}

FString UTCPSocketServer::StringFromBinaryArray(const TArray<uint8>& BinaryArray)
{
	return FString(ANSI_TO_TCHAR(reinterpret_cast<const char*>(BinaryArray.GetData())));
}

蓝图调用

在这里插入图片描述

存在的问题

不支持发送非ASCII的数据
接收也是一样的,需要发送HEX数据的人自己修改

如果不修改直接接收/发送HEX格式数据 会导致崩溃

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值