UE4引擎是提供了Sockets模块和Networking模块的,博主在研究此功能时也是参考的Sockets模块和Networking模块的源码,其中引擎为我们提供了一些实例类很有参考价值,比如Sockets模块中的MultichannelTcpReceiver.h和MultichannelTcpSender.h,Networking模块中的UdpSocketReceiver.h和UdpSocketSender.h。博主的例子就是研究参考了以上代码写出来的。
UnrealEngine 4.15 , Visual Studio 2015
博主的例子实现的是一个使用Socket多线程TCP通信的客户端。在主线程中发消息,子线程中收消息。当然也能类似的实现两个子线程分别收发消息。Socket相关函数都定义在了GameInstance中,以便我们能在不同场景都能调用。
此处使用了一个有简单收发功能的服务器,用VS2015新建空项目即可:
//SocketTest.cpp: Defines the entry point for the console application #include <stdio.h> #include <string> #include <iostream> #include <WinSock2.h> #include <WS2tcpip.h> #pragma comment(lib, "WS2_32.lib") using namespace std; int main() { WSADATA wsaData; SOCKET serverSock; SOCKADDR_IN serverAddr; SOCKET clientSock; SOCKADDR_IN clientAddr; cout << "Server Start!" << endl; //加载套接字库 int err = WSAStartup(MAKEWORD(2, 2), &wsaData); if (0 != err) { cout << "WSAStartup failed!" << endl; return 1; } //构造监听SOCKET,流式SOCKET serverSock = socket(AF_INET, SOCK_STREAM, 0); //配置监听地址和端口 serverAddr.sin_family = AF_INET; serverAddr.sin_port = htons(4399); //本地监听端口:4399 serverAddr.sin_addr.S_un.S_addr = INADDR_ANY; //绑定SOCKET int retVal = bind(serverSock, (SOCKADDR*)&serverAddr, sizeof(serverAddr)); if (SOCKET_ERROR == retVal) { cout << "bind failed!" << endl; closesocket(serverSock); WSACleanup(); return -1; } retVal = listen(serverSock, 5); if (SOCKET_ERROR == retVal) { cout << "listen failed!" << endl; closesocket(serverSock); WSACleanup(); return -1; } char IPdot[20] = { '\0' }; inet_ntop(AF_INET, (void*)&serverAddr.sin_addr, IPdot, 16); printf("Welcome,the Host %s is running!Now Wating for someone comes in!\n", IPdot); int addrClientlen = sizeof(clientAddr); //等待客户端连接 clientSock = accept(serverSock, (SOCKADDR*)&clientAddr, &addrClientlen); while (1) { //发送数据 char sendBuff[50]; //sprintf_s(sendBuff, "welcome %s to here", inet_ntoa(clientAddr.sin_addr)); char IPdotdec[20] = { '\0' }; inet_ntop(AF_INET, (void*)&clientAddr.sin_addr, IPdotdec, 16); sprintf_s(sendBuff, "From Server: welcome %s to here", IPdotdec); send(clientSock, sendBuff, strlen(sendBuff) + 1, 0); //接收数据 char recvBuff[50]; recv(clientSock, recvBuff, 50, 0); printf(" %s \n\n", recvBuff); Sleep(1000); } //关闭套接字,关闭加载的套接字库 closesocket(serverSock); WSACleanup(); return 0; }新建项目,在.Build.cs文件中添加Sockets模块和Networking模块:
// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. using UnrealBuildTool; public class SocketThread : ModuleRules { public SocketThread(TargetInfo Target) { PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "HeadMountedDisplay","Sockets", "Networking" }); } }在编辑器中,创建我们之前定义的GameInstance的蓝图类,并在Project Setting中设其为默认GameInstance。创建一个GameMode,在他的EventGraph中添加如下蓝图逻辑: 其中Succe是一个bool类型变量,Index是一个Int类型变量,不改默认值。 之后将这个GameMode绑定到当前场景中,编译运行服务器,然后Play,大功告成!博主运行结果如下: 可以看到,收发消息都成功了。
