USocket UE4TCP UDP接口

本文档介绍了如何将USocket编译为DLL,并在UE4中使用。内容包括USocket的DLL实现、头文件接口定义、LIBUSOCKET.h作为蓝图函数库的接入API,以及LibUSocket.cpp中的虚幻DLL调用。此外,还讨论了非阻塞模式下USocket组件的使用接口。

  
  
// USocket.cpp : 定义控制台应用程序的入口点。 // //#define printf_s printf
#include "stdafx.h" #include "USocket.h"
#include <stdio.h> #include <list>
OnReceive* OnTCPReceive; OnServerAccept* OnServeAccept; OnReceiveForm* OnServerReceive; OnReceiveForm* OnUDPReceive;
void UDPReceiveThread(SOCKET* udpclient); void TCPReceiveThread(SOCKET* client);
void ServerReceiveThread(PeerSocket* peer); void ServerAcceptThread(SOCKET* server);
std::list<SOCKET*>* tcpclients; std::list<SOCKET*>* udpclients; std::list<SOCKET*>* tcpservers;
WSADATA wsaData;
void Init() {  tcpclients = new std::list<SOCKET*>();  udpclients = new std::list<SOCKET*>();  tcpservers = new std::list<SOCKET*>();  int result = WSAStartup(MAKEWORD(2, 2), &wsaData);  if (result)printf_s("Init error:%d\n", WSAGetLastError()); }
FILE* consolefile; void OpenConsole() {  AllocConsole();  freopen_s(&consolefile, "CONOUT$", "w+t", stdout);  //consolefile = freopen("CONOUT$", "w+t", stdout); }
void CloseConsole() {  fclose(consolefile);  FreeConsole(); }
void Shutdown() {  WSACleanup(); }
SOCKET* CreateTCPClient(unsigned short port) {  SOCKET* sockClient = new SOCKET();  *sockClient = socket(AF_INET, SOCK_STREAM, 0);
 int result = 0;  sockaddr_in addrClient;  int addrlen = sizeof(sockaddr);  if (port)  {//绑定自定义端口   addrClient.sin_family = AF_INET;   addrClient.sin_addr.s_addr = inet_addr("127.0.0.1");   addrClient.sin_port = htons(port);   result |= bind(*sockClient, (SOCKADDR*)&addrClient, sizeof(addrClient));   if (result)printf_s("CreateTCPClient error:%d\n", WSAGetLastError());
  result |= getsockname(*sockClient, (sockaddr*)&addrClient, &addrlen);   if (result)printf_s("CreateTCPClient error:%d\n", WSAGetLastError());   printf_s("TCP指定端口:%s:%d\n", inet_ntoa(addrClient.sin_addr), ntohs(addrClient.sin_port));  }  else  {   printf_s("TCP端口未指定\n");  }
 tcpclients->push_back(sockClient);  return sockClient; }
SOCKET* CreateTCPServer(unsigned short port) {  SOCKET* sockServer = new SOCKET();  *sockServer = socket(AF_INET, SOCK_STREAM, 0);
 int result = 0;  sockaddr_in addrServer;  int addrlen = sizeof(sockaddr);  if (port)  {//绑定自定义端口   addrServer.sin_family = AF_INET;   addrServer.sin_addr.s_addr = inet_addr("127.0.0.1");   addrServer.sin_port = htons(port);   result |= bind(*sockServer, (SOCKADDR*)&addrServer, sizeof(addrServer));   if (result)printf_s("CreateTCPServer error:%d\n", WSAGetLastError());
  result |= getsockname(*sockServer, (sockaddr*)&addrServer, &addrlen);   if (result)printf_s("CreateTCPServer error:%d\n", WSAGetLastError());   printf_s("指定端口:%s:%d\n", inet_ntoa(addrServer.sin_addr), ntohs(addrServer.sin_port));  }  else  {   printf_s("服务端未分配端口\n");  }
 tcpservers->push_back(sockServer);  return sockServer; }
void ServerListenAccept(SOCKET* server, int maxconn) {  int i = 0;  int result = listen(*server, maxconn);  if (result)printf_s("ServerListenAccept error:%d\n", WSAGetLastError());
 sockaddr_in addrClient;  int addrlen;  do  {   SOCKET client = accept(*server, 0, 0);   if (client == INVALID_SOCKET)   {    printf_s("无效socket, error:%d\n", WSAGetLastError());    continue;   }   result |= getsockname(client, (sockaddr*)&addrClient, &addrlen);   if (result)printf_s("ServerListenAccept error:%d\n", WSAGetLastError());   printf_s("连接客户端:%s:%d\n", inet_ntoa(addrClient.sin_addr), ntohs(addrClient.sin_port));   i += 1;  } while (i < maxconn);  printf_s("连接客户端数已经最大"); }
void ServerListenAcceptAsync(SOCKET* server, int maxconn) {  int result = 0;  result = listen(*server, maxconn);  if (result)printf_s("ServerListenAcceptAsync error:%d\n", WSAGetLastError());
 DWORD threadID;  HANDLE hThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)ServerAcceptThread, server, 0, &threadID);  printf_s("接受线程:%d, Thread ID:%d\n", hThread, threadID); }
SOCKET* CreateUDPClient(unsigned short port) {  SOCKET* sockClient = new SOCKET();  *sockClient = socket(AF_INET, SOCK_DGRAM, 0);
 int result = 0;  sockaddr_in addrClient;  int addrlen = sizeof(sockaddr);  if (port)  {//绑定自定义端口   addrClient.sin_family = AF_INET;   addrClient.sin_addr.s_addr = inet_addr("127.0.0.1");   addrClient.sin_port = htons(port);   result |= bind(*sockClient, (SOCKADDR*)&addrClient, sizeof(addrClient));   if (result)printf_s("CreateUDPClient error:%d\n", WSAGetLastError());
  result |= getsockname(*sockClient, (sockaddr*)&addrClient, &addrlen);   if (result)printf_s("CreateUDPClient error:%d\n", WSAGetLastError());   printf_s("UDP指定端口:%s:%d\n", inet_ntoa(addrClient.sin_addr), ntohs(addrClient.sin_port));  }  else  {   getsockname(*sockClient, (sockaddr*)&addrClient, &addrlen);   printf_s("TCP端口未指定\n");  }
 udpclients->push_back(sockClient);  return sockClient; }
int SocketIONonBlocking(SOCKET* s, int mode) {  u_long iMode = mode;  int result = ioctlsocket(*s, FIONBIO, &iMode);  if (result)printf_s("error:%d\n", WSAGetLastError());  return result; }
int TCPConnectToServer(SOCKET* sockClient, char* IP, unsigned short port) {  printf_s("参数 %s:%d\n", IP, port);  int result = 0;  SOCKADDR_IN addrServer;  addrServer.sin_addr.S_un.S_addr = inet_addr(IP);  addrServer.sin_family = AF_INET;  addrServer.sin_port = htons(port);  result |= connect(*sockClient, (SOCKADDR*)&addrServer, sizeof(SOCKADDR));  if (result)printf_s("TCPConnectToServer error:%d\n", WSAGetLastError());
 sockaddr_in addrClient;  int addrlen = sizeof(sockaddr);  result |= getsockname(*sockClient, (sockaddr*)&addrClient, &addrlen);  if (result)printf_s("TCPConnectToServer error:%d\n", WSAGetLastError());  printf_s("TCP连接端口:%s:%d\n", inet_ntoa(addrClient.sin_addr), ntohs(addrClient.sin_port));  return result;//一直为0代表无错误 }
void SetTCPReceiveC
### UDP协议在Unreal Engine中的实现与分析 #### 1. 默认网络通信机制 Unreal Engine 默认采用 UDP 协议进行网络通信,这是因为多人联机游戏对延迟有较高的要求。UDP 提供了较低的延迟和更高的吞吐量,适合于实时性强的游戏场景[^1]。 #### 2. 网络架构灵活性 尽管 Unreal Engine 默认使用 UDP,但它也允许开发者根据实际需求切换到 TCP 协议。这种灵活性使得开发者能够通过配置文件或代码调整网络设置,从而满足特定的应用场景需求。 #### 3. 开源项目支持 为了进一步简化 UDP 的使用,社区中存在多个开源项目,例如 **UDP-Unreal** 和 **UDP/TCP 插件**。这些工具不仅优化了 UDP 封装逻辑,还提供了与现有框架(如 SocketIOClient-Unreal)的良好兼容性,显著降低了开发难度[^2][^5]。 #### 4. 技术细节剖析 在网络编程层面,理解客户端-服务器模型对于掌握 UDP 在 Unreal Engine 中的工作方式至关重要。该模型定义了数据如何在不同节点之间传递,并强调了低延迟的重要性。此外,在 C++ 层面操作时,开发者需熟悉 IP 地址、端口号以及数据包结构等相关基础知识[^3]。 以下是基于 C++ 实现的一个简单示例,展示如何初始化并发送一条消息: ```cpp // 初始化Socket子系统 FString SocketSubsystemName = TEXT("sockets"); ISocketSubsystem* SocketSubsystem = ISocketSubsystem::Get(SocketSubsystemName); if (SocketSubsystem != nullptr) { // 创建IPv4地址对象 TSharedRef<FInternetAddr> RemoteAddress = SocketSubsystem->CreateInternetAddr(); bool bIsValid; RemoteAddress->SetIp(*RemoteIPAddress, bIsValid); RemoteAddress->SetPort(RemotePort); if (!bIsValid) { UE_LOG(LogTemp, Error, TEXT("Invalid remote address")); return false; } // 建立UDP套接字 FUdpSocketBuilder SocketBuilder(TEXT("UdpSender")); USocket = SocketBuilder.AsNonBlocking().BoundTo(LocalPort).WithReceiving(); // 发送数据 uint8 BufferToSend[sizeof(FVector)]; FMemory::Memcpy(BufferToSend, &DataToFsend, sizeof(DataToFsend)); int32 BytesSent; if (USocket->SendTo(BufferToSend, sizeof(BufferToSend), BytesSent, *RemoteAddress)) { UE_LOG(LogTemp, Log, TEXT("Successfully sent %d bytes"), BytesSent); } } ``` 此代码片段展示了如何构建一个基本的 UDP 连接,并向远程目标发送数据包。 #### 5. 性能调优建议 当利用 UDP 协议开发高性能应用时,应考虑以下几个方面: - 数据压缩:减少每帧传输的数据大小以降低带宽消耗。 - 可靠性处理:虽然 UDP 不提供内置可靠性保障,但可通过自定义重传机制弥补这一不足。 - 流量控制:合理分配资源,防止因过载而导致丢包现象加剧。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值