需求
在项目中,需要多个按钮的按压和释放事件触发后发送消息,因此创建一个C++单例模式的类,用于收发消息。
准备
在xxx.Build.cs中添加Networking和Sockets模块。
PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "Networking", "Sockets"});
代码
#pragma once
#include "CoreMinimal.h"
#include "Networking.h"
class MySocket
{
public:
MySocket();
~MySocket();
static MySocket* GetInstance();
void SendMessage(const FString& Message, const FString& Ip, const int& Port);
void ReceiveMessage(const FArrayReaderPtr& ArrayReader, const FIPv4Endpoint& Endpoint);
private:
void Init();
static MySocket* m_pInstance;
FSocket* m_pUdpSocket;
FUdpSocketReceiver* m_pSocketReceiver;
};
#include "MySocket.h"
MySocket* MySocket::m_pInstance = nullptr;
MySocket::MySocket()
{
}
MySocket::~MySocket()
{
}
MySocket* MySocket::GetInstance()
{
if (m_pInstance == nullptr)
{
m_pInstance = new MySocket;
m_pInstance->Init();
}
return m_pInstance;
}
void MySocket::Init()
{
FIPv4Address UdpAddr;
FIPv4Address::Parse("10.28.5.138", UdpAddr);//本机IP,将字符串转换为IPv4地址
FIPv4Endpoint Endpoint(UdpAddr, 41450);//本机端口
int32 BufferSize = 4096;//缓冲区大小,根据具体情况而定
FUdpSocketBuilder SocketBuilder = FUdpSocketBuilder(TEXT("m_pUdpSocket"));
SocketBuilder.BoundToEndpoint(Endpoint);//绑定地址
SocketBuilder.WithReceiveBufferSize(BufferSize);//设置缓冲区大小
SocketBuilder.AsNonBlocking();//非阻塞
m_UdpSocket = SocketBuilder;
FTimespan Timespan = FTimespan::FromMilliseconds(20);//检查缓冲区间隔时间
m_pSocketReceiver = new FUdpSocketReceiver(m_pUdpSocket, Timespan, TEXT("m_pSocketReceiver"));
m_pSocketReceiver->OnDataReceived().BindRaw(this, &MySocket::ReceiveMessage);//绑定接收回调函数
m_pSocketReceiver->Start();
}
void MySocket::SendMessage(const FString& Message, const FString& Ip, const int& Port)
{
TArray<uint8> Send_array;
FString stringSend = Message;
TCHAR* str = stringSend.GetCharArray().GetData();
int32 str_len = FCString::Strlen(str);
for (int j = 0; j < str_len; j++)
{
// Generic types for almost all compilersand platforms
uint8* dst = (uint8*)TCHAR_TO_UTF8(str);
Send_array.Add(*dst);
str++;
}
static TSharedPtr<FInternetAddr> InternetAddr;
if (!InternetAddr.IsValid())
{
InternetAddr = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateInternetAddr();
}
bool bIsValid = false;
InternetAddr->SetIp(*Ip, bIsValid);
InternetAddr->SetPort(Port);
int32 BytesSent = 0;
m_UdpSocket->SendTo(Send_array.GetData(), Send_array.Num(), BytesSent, *InternetAddr);
}
void MySocket::ReceiveMessage(const FArrayReaderPtr& ArrayReader, const FIPv4Endpoint& Endpoint)
{
uint8* RecvData = ArrayReader->GetData();
uint8 data[1024];
FMemory::Memzero(data, 1024);
FMemory::Memcpy(data, ArrayReader->GetData(), ArrayReader->Num());//复制到data
FString Message = ((const char*)data);
//处理Message...
}
注:推荐将IP和端口写入配置文件。