# 网络连接
# UE4中TCP
下面是UE4中C++实现的TCP连接:
# TCP客户端
ATCPClient.h文件:
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "SocketRSThread.h"
#include "TCPClient.generated.h"
UCLASS(BlueprintType, Blueprintable)
class TESTNETWORK_API ATCPClient : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
ATCPClient();
UFUNCTION(BlueprintCallable, Category = Network)
void CreateClientAndConnect(FString ServerIP, int32 Port, int32 ReceiveSize = 1024, int32 SendSize = 1024);
UFUNCTION(Category = Network)
bool ConnectServer(FString ServerIP, int32 Port);
UFUNCTION(BlueprintCallable, Category = Network)
void SendToServer(FString Message);
UPROPERTY(BlueprintAssignable, VisibleAnywhere, Category = Network)
FReceiveSocketDataDelegate ReceiveSocketDataDelegate;
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
UFUNCTION()
void OnServerDisconnect(class USocketRSThread* pThread);
class FSocket* ClientSocket;
int32 SendDataSize;
int32 RecDataDize;
TArray<class USocketRSThread*> RecThreads;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
ATCPClient.cpp:
#include "TCPClient.h"
// Sets default values
ATCPClient::ATCPClient()
{
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
}
// Called when the game starts or when spawned
void ATCPClient::BeginPlay()
{
Super::BeginPlay();
}
// Called every frame
void ATCPClient::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
void ATCPClient::EndPlay(const EEndPlayReason::Type EndPlayReason)
{
if (ClientSocket)
{
for (auto RecThreald : RecThreads)
{
RecThreald->Stop();
}
}
}
void ATCPClient::OnServerDisconnect(USocketRSThread* pThread)
{
UE_LOG(LogTemp, Warning, TEXT("Server lost"));
RecThreads.Remove(pThread);
}
void ATCPClient::CreateClientAndConnect(FString ServerIP, int32 Port, int32 ReceiveSize, int32 SendSize)
{
this->SendDataSize = SendSize;
this->RecDataDize = ReceiveSize;
ClientSocket = FTcpSocketBuilder(TEXT("Client Socket"))
.AsReusable()
.AsBlocking()
.WithReceiveBufferSize(ReceiveSize)
.WithSendBufferSize(SendSize);
if (!ClientSocket)
{
UE_LOG(LogTemp, Error, TEXT("Create Client Socket Error!"));
}
else
{
ConnectServer(ServerIP, Port);
}
}
bool ATCPClient::ConnectServer(FString ServerIP, int32 Port)
{
FIPv4Endpoint ServerEndpoint;
FIPv4Endpoint::Parse(ServerIP, ServerEndpoint);
TSharedPtr<FInternetAddr> addr = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateInternetAddr();
bool Success = true;
addr->SetIp(*ServerIP, Success);
if (!Success)
{
return false;
}
addr->SetPort(Port);
if (ClientSocket->Connect(*addr))
{
USocketRSThread* RSThread = NewObject<USocketRSThread>();
RecThreads.Add(RSThread);
RSThread->ReceiveSocketDataDelegate = ReceiveSocketDataDelegate;
RSThread->LostConnectionDelegate.AddDynamic(this, &ATCPClient::OnServerDisconnect);
RSThread->Start(ClientSocket, SendDataSize, RecDataDize);
UE_LOG(LogTemp, Warning, TEXT("Client Connect Success"));
return true;
}
else
{
ESocketErrors LastErr = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->GetLastErrorCode();
UE_LOG(LogTemp, Warning, TEXT("Connect failed with error code (%d) error (%s)"), LastErr, ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->GetSocketError(LastErr));
ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->DestroySocket(ClientSocket);
}
return false;
}
void ATCPClient::SendToServer(FString Message)
{
for (auto SocketThread : RecThreads)
{
SocketThread->Send(Message);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# TCP服务端
ATCPServer.h文件:
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "SocketRSThread.h"
#include "TCPServer.generated.h"
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FServerSocketCreateDelegate, bool, bSuccess);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FConnectReceiveDelegate, FString, RemoteIP, int32, RemotePort);
UCLASS(BlueprintType, Blueprintable)
class TESTNETWORK_API ATCPServer : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
ATCPServer();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
/**
* 创建服务器Socket
* @ServerIP-服务器的IP地址
* @ServerPort-服务器的端口号
* @ReceiveBufferSize-接受数据大小
* @SendBufferSize-发送数据大小
*/
UFUNCTION(BlueprintCallable, Category = Network)
void CreateServer(const FString& ServerIP, int32 ServerPort, int32 ReceiveBufferSize = 1024, int32 SendBufferSize = 1024);
/** 关闭Server */
UFUNCTION(BlueprintCallable, Category = Network)
void CloseServer();
/** 检测是否有客户端连入 */
void ConnectCheck();
UFUNCTION(BlueprintCallable, Category = Network)
void SendToClient(FString Message);
UFUNCTION(Category = Network)
void OnClientDisconnect(class USocketRSThread* pThread);
protected:
int32 SendDataSize;
int32 RecDataDize;
class FSocket* serverSocket;
UPROPERTY(BlueprintAssignable, VisibleAnywhere, Category = Network)
FServerSocketCreateDelegate SocketCreateDelegate;
UPROPERTY(BlueprintAssignable, VisibleAnywhere, Category = Network)
FConnectReceiveDelegate ConnectReceiveDelegate;
UPROPERTY(BlueprintAssignable, VisibleAnywhere, Category = Network)
FReceiveSocketDataDelegate ReceiveSocketDataDelegate;
FTimerHandle ConnectCheckHandler;
TArray<USocketRSThread*> RecThreads;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
ATCPServer.cpp文件:
#include "TCPServer.h"
// Sets default values
ATCPServer::ATCPServer()
{
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
}
// Called when the game starts or when spawned
void ATCPServer::BeginPlay()
{
Super::BeginPlay();
}
void ATCPServer::EndPlay(const EEndPlayReason::Type EndPlayReason)
{
CloseServer();
Super::EndPlay(EndPlayReason);
}
// Called every frame
void ATCPServer::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
void ATCPServer::CreateServer(const FString& ServerIP, int32 ServerPort, int32 ReceiveBufferSize, int32 SendBufferSize)
{
this->RecDataDize = ReceiveBufferSize;
this->SendDataSize = SendBufferSize;
FIPv4Address ServerAddr;
if (!FIPv4Address::Parse(ServerIP, ServerAddr))
{
UE_LOG(LogTemp, Error, TEXT("Server Ip %s is illegal"), *ServerIP);
}
serverSocket = FTcpSocketBuilder(TEXT("Socket Listener"))
.AsReusable()
.AsBlocking()
.BoundToAddress(ServerAddr)
.BoundToPort(ServerPort)
.Listening(8)
.WithReceiveBufferSize(ReceiveBufferSize)
.WithSendBufferSize(SendBufferSize);
if (serverSocket)
{
UE_LOG(LogTemp, Warning, TEXT("Server Create Success!"), *ServerIP);
SocketCreateDelegate.Broadcast(true);
GetWorld()->GetTimerManager().SetTimer(ConnectCheckHandler, this, &ATCPServer::ConnectCheck, 1, true);
}
else
{
UE_LOG(LogTemp, Error, TEXT("Server Create Failed!"));
SocketCreateDelegate.Broadcast(false);
}
}
void ATCPServer::CloseServer()
{
if (serverSocket)
{
serverSocket->Close();
for (auto RecThreald : RecThreads)
{
RecThreald->Stop();
}
ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->DestroySocket(serverSocket);
}
}
void ATCPServer::ConnectCheck()
{
bool bPending = false;
if (serverSocket->HasPendingConnection(bPending) && bPending)
{
//有新的socket连接进来
TSharedRef<FInternetAddr> RemoteAddress = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateInternetAddr();
FSocket* RecSocket = serverSocket->Accept(*RemoteAddress, TEXT("Receive Socket"));
USocketRSThread* RSThread = NewObject<USocketRSThread>();
RecThreads.Add(RSThread);
RSThread->ReceiveSocketDataDelegate = ReceiveSocketDataDelegate;
RSThread->LostConnectionDelegate.AddDynamic(this, &ATCPServer::OnClientDisconnect);
RSThread->Start(RecSocket, SendDataSize, RecDataDize);
ConnectReceiveDelegate.Broadcast(RemoteAddress->ToString(false), RemoteAddress->GetPort());
}
}
void ATCPServer::SendToClient(FString Message)
{
for (auto SocketThread : RecThreads)
{
SocketThread->Send(Message);
}
}
void ATCPServer::OnClientDisconnect(USocketRSThread* pThread)
{
UE_LOG(LogTemp, Warning, TEXT("Client lost"));
RecThreads.Remove(pThread);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# 收发线程
下面是收发线程类实现。
USocketRSThread.h:
#pragma once
#include "CoreMinimal.h"
#include "Sockets.h"
#include "HAL/Runnable.h"
#include "Networking/Public/Common/TcpSocketBuilder.h"
#include "SocketRSThread.generated.h"
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FReceiveSocketDataDelegate, FString, Data);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FLostConnectionDelegate, USocketRSThread*, Thread);
/**
* Socket数据收 发线程
*/
UCLASS()
class TESTNETWORK_API USocketRSThread : public UObject, public FRunnable
{
GENERATED_BODY()
public:
// 线程接口
virtual bool Init() override { return true; }
virtual uint32 Run() override;
virtual void Stop() override;
virtual void Exit() override {}
// End FRunnable Interface
void Start(FSocket* Socket, uint32 SendDataSize, uint32 RecDataSize);
void Send(FString Message);
FReceiveSocketDataDelegate ReceiveSocketDataDelegate;
FLostConnectionDelegate LostConnectionDelegate;
protected:
FSocket* ConnectSocket;
uint32 SendDataSize;
uint32 RecDataSize;
TArray<uint8> ReceiveData;
/** 线程相关 */
FRunnableThread* pThread;
bool bThreadStop;
//socket默认使用utf8格式传输数据,如果传输的是中文的话,那么1个中文占用3个字节,发送的个数就需要针对性就行修改,不能简单的使用FString::Len()进行个数计算,这里给出一个计算个数的函数
int32 CalcUtf8NumFromString(const FString& Str);
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
USocketRSThread.cpp:
#include "SocketRSThread.h"
#include "SocketSubsystem.h"
uint32 USocketRSThread::Run()
{
while (!bThreadStop)
{
//这个地方是之前将socket设置为阻塞模式 在这里5s内判断是否断开连接
uint32 Size;
bool LostConnect = false;
ConnectSocket->HasPendingConnection(LostConnect);
ConnectSocket->Wait(ESocketWaitConditions::WaitForReadOrWrite, FTimespan(0, 0, 5));
if (LostConnect)
{
//UE_LOG(LogTemp, Warning, TEXT(" doesn't Connect "));
Stop();
LostConnectionDelegate.Broadcast(this);
continue;
}
/** 处理接收数据 */
if (ConnectSocket && ConnectSocket->HasPendingData(Size))
{
ReceiveData.Init(0, FMath::Min(Size, RecDataSize));
int32 Readed;
ConnectSocket->Recv(ReceiveData.GetData(), RecDataSize, Readed);
FString ReceivedString = FString((UTF8_TO_TCHAR(ReceiveData.GetData())));
//FString ReceivedString = FString(ANSI_TO_TCHAR(reinterpret_cast<const char*>(ReceiveData.GetData())));
ReceiveSocketDataDelegate.Broadcast(ReceivedString);
}
}
return 0;
}
void USocketRSThread::Start(FSocket* Socket, uint32 SendDataSizeP, uint32 RecDataSizeP)
{
this->ConnectSocket = Socket;
this->SendDataSize = SendDataSizeP;
this->RecDataSize = RecDataSizeP;
FRunnableThread::Create(this, TEXT("Receive Threald"));
}
void USocketRSThread::Stop()
{
bThreadStop = true;
ConnectSocket->Close();
ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->DestroySocket(ConnectSocket);
ConnectSocket = nullptr;
}
void USocketRSThread::Send(FString Message)
{
///** 处理发送数据 */
TCHAR* SendMessage = Message.GetCharArray().GetData();
//int32 size = FCString::Strlen(SendMessage) + 1;
int32 size = CalcUtf8NumFromString(Message);
//int32 size = sizeof(SendMessage);
int32 sent = 0;
if (size >= (int32)SendDataSize)
{
UE_LOG(LogTemp, Error, TEXT("Send Data Size is Larger than Max Size for set"));
}
else
{
if (ConnectSocket && ConnectSocket->Send((uint8*)TCHAR_TO_UTF8(SendMessage), size, sent))
{
UE_LOG(LogTemp, Warning, TEXT("___Send Succeed!"));
}
else
{
UE_LOG(LogTemp, Error, TEXT("___Send Failed!"));
}
}
}
int32 USocketRSThread::CalcUtf8NumFromString(const FString& Str)
{
int32 result = 0;
for (int i = 0; i < Str.Len(); i++)
{
if (Str[i] <= 0x7f)
result = result + 1;
else if (Str[i] > 0x7f && Str[i] <= 0x07ff)
result = result + 2;
else if (Str[i] > 0x07ff && Str[i] <= 0xffff)
result = result + 3;
else
result = result + 4;
}
return result + 1;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102