UDPDataTypes.h
定义数据包结构
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "UDPDataTypes.generated.h"
#pragma pack(push)
#pragma pack(1)
struct FMessageDefinition
{
public:
char name[10];
float x;
float y;
float z;
};
#pragma pack(pop)
USTRUCT(BlueprintType)
struct FTestMessage
{
GENERATED_USTRUCT_BODY()
UPROPERTY(BlueprintReadWrite)
int32 testPlayer;
FTestMessage()
{
testPlayer = 0;
}
};
1、发送类 AUDPSenderActor,如下
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Networking.h"
#include"UDPDataTypes.h"
#include "UDPSenderActor.generated.h"
UCLASS()
class FACEARSAMPLE_API AUDPSenderActor : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
AUDPSenderActor();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
FSocket* SendSocket = nullptr;
FUdpSocketSender* UDPSender = nullptr;
FMessageDefinition MessageData;
FIPv4Endpoint CurEndpoint;
int32 nSendFlag = 0;
FString SendIP;
int32 SendPort;
int32 NetType;//1 发送 2接收
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
UFUNCTION(BlueprintCallable, Category = "FindIP")
bool Start(const FString TheIP, const int32 ThePort);//ThePort 绑定广播端口,在本类蓝图begin函数调用
bool UDPSendData(FMessageDefinition& DefInfo);
FTimerHandle TimerHandle_UDPSendData;
void TimerUDPSendData();
};
// Fill out your copyright notice in the Description page of Project Settings.
#include "UDPSenderActor.h"
#include <iostream>
#include <string>
using namespace std;
// Sets default values
AUDPSenderActor::AUDPSenderActor()
{
// 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 AUDPSenderActor::BeginPlay()
{
Super::BeginPlay();
FString StrNetType;
FParse::Value(FCommandLine::Get(), TEXT("NetType="), StrNetType);
NetType = FCString::Atoi(*StrNetType);
UE_LOG(LogTemp, Log, TEXT("AUDPSenderActor::BeginPlay NetType=%d"), NetType);
FString FilePath = FPaths::Combine(*FPaths::ProjectDir(), TEXT("NetConfig.ini"));
if (!GConfig)
{
return ;
}
bool Result;
Result = GConfig->GetInt(
TEXT("NetSend"),
TEXT("SendFlag"),
nSendFlag,
FilePath
);
Result = GConfig->GetInt(
TEXT("NetSend"),
TEXT("SendPort"),
SendPort,
FilePath
);
Result = GConfig->GetString(
TEXT("NetSend"),
TEXT("SendIP"),
SendIP,
FilePath
);
UE_LOG(LogTemp, Log, TEXT("AUDPSenderActor::BeginPlay nSendFlag=%d"), nSendFlag);
/*if (1== nSendFlag)
{
Start(SendIP, SendPort);
GetWorldTimerManager().SetTimer(TimerHandle_UDPSendData, this, &AUDPSenderActor::TimerUDPSendData, 0.01, true);
}*/
if (1 == NetType)
{
Start(SendIP, SendPort);
GetWorldTimerManager().SetTimer(TimerHandle_UDPSendData, this, &AUDPSenderActor::TimerUDPSendData, 0.01, true);
}
}
// Called every frame
void AUDPSenderActor::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
void AUDPSenderActor::EndPlay(const EEndPlayReason::Type EndPlayReason)
{
Super::EndPlay(EndPlayReason);
GetWorldTimerManager().ClearTimer(TimerHandle_UDPSendData);
delete UDPSender;
UDPSender = nullptr;
if (SendSocket)
{
SendSocket->Close();
ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->DestroySocket(SendSocket);
SendSocket = nullptr;
}
}
bool AUDPSenderActor::Start(const FString TheIP,const int32 ThePort)
{
// Create Socket
// FIPv4Endpoint Endpoint(FIPv4Address(0, 0, 0, 0), ThePort);
//接收固定IP和端口 消息 begin
//FString TheIP = TEXT("192.168.50.5");
//FIPv4Address Addr;
//FIPv4Address::Parse(TheIP, Addr);
//FIPv4Endpoint Endpoint(Addr, ThePort);
//接收固定IP和端口 消息 begin
//FIPv4Endpoint Endpoint(FIPv4Address::Any, ThePort);所有ip地址本地 FIPv4Address::Any FIPv4Address::InternalLoopback FIPv4Address::LanBroadcast
FIPv4Address Addr;
FIPv4Address::Parse(TheIP, Addr);
FIPv4Endpoint Endpoint(Addr,ThePort);
CurEndpoint = Endpoint;
//BUFFER SIZE
int32 BufferSize = 2 * 1024 * 1024;
SendSocket = FUdpSocketBuilder(TEXT("UdpSocketBuilderSocket2"))
.AsNonBlocking()
.WithBroadcast()
.AsReusable()
//.WithMulticastInterface(Addr)
//.BoundToEndpoint(Endpoint)
.WithSendBufferSize(BufferSize);
SendSocket->SetSendBufferSize(BufferSize, BufferSize);
SendSocket->SetReceiveBufferSize(BufferSize, BufferSize);
//FTimespan ThreadWaitTime = FTimespan::FromMilliseconds(100);
UDPSender = new FUdpSocketSender(SendSocket, TEXT("UdpSocketSenderThread"));
return true;
}
void AUDPSenderActor::TimerUDPSendData()
{
FMessageDefinition Info;
const char src[50] = "Hello";
memcpy(Info.name, src, strlen(src) + 1);
Info.x = GetWorld()->GetRealTimeSeconds();
Info.y = 0.5;
Info.z = 0.8;
UDPSendData(Info);
}
bool AUDPSenderActor::UDPSendData(FMessageDefinition& DefInfo)
{
/*FString TestStr;
TArray<uint8> ContentData;
ContentData.SetNum(TestStr.Len());
memcpy(ContentData.GetData(), TCHAR_TO_ANSI(*TestStr), TestStr.Len());*/
std::string strName;
strName = DefInfo.name;
FString CurName(UTF8_TO_TCHAR(strName.c_str()));
UE_LOG(LogTemp, Log, TEXT("UDPSenderActor::UDPSendData CurName=%s"), *CurName);
TArray<uint8> ContentData;
ContentData.SetNum(sizeof(DefInfo));
//memcpy(ContentData.GetData(), (uint8*)&DefInfo, sizeof(DefInfo));
FMemory::Memcpy(ContentData.GetData(), (uint8*)&DefInfo, sizeof(DefInfo));
TSharedRef<TArray<uint8>, ESPMode::ThreadSafe> TemContentData = MakeShared<TArray<uint8>, ESPMode::ThreadSafe>(ContentData);
bool r = UDPSender->Send(TemContentData, CurEndpoint);
return r;
return true;
}
2、接收类 AUDPReceiverActor,如下
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Networking.h"
#include"UDPDataTypes.h"
#include "UDPReceiverActor.generated.h"
UCLASS()
class FACEARSAMPLE_API AUDPReceiverActor : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
AUDPReceiverActor();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
FSocket* ReceiveSocket = nullptr;
FUdpSocketReceiver* UDPReceiver = nullptr;
FMessageDefinition MessageData;
int32 nReceiveFlag = 0;
FString ReceiveIP;
int32 ReceivePort;
int32 NetType;//1 发送 2接收
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
UFUNCTION(BlueprintCallable, Category = "FindIP")
bool Start(const FString TheIP, const int32 ThePort);//ThePort 绑定广播端口,在本类蓝图begin函数调用
void Recv(const FArrayReaderPtr& ArrayReader, const FIPv4Endpoint& Endpoint);
};
// Fill out your copyright notice in the Description page of Project Settings.
#include "UDPReceiverActor.h"
#include <iostream>
#include <string>
using namespace std;
// Sets default values
AUDPReceiverActor::AUDPReceiverActor()
{
// 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 AUDPReceiverActor::BeginPlay()
{
Super::BeginPlay();
FString StrNetType;
FParse::Value(FCommandLine::Get(), TEXT("NetType="), StrNetType);
NetType = FCString::Atoi(*StrNetType);
UE_LOG(LogTemp, Log, TEXT("AUDPReceiverActor::BeginPlay NetType=%d"), NetType);
FString FilePath = FPaths::Combine(*FPaths::ProjectDir(), TEXT("NetConfig.ini"));
if (!GConfig)
{
return;
}
bool Result;
Result = GConfig->GetInt(
TEXT("NetReceive"),
TEXT("ReceiveFlag"),
nReceiveFlag,
FilePath
);
Result = GConfig->GetInt(
TEXT("NetReceive"),
TEXT("ReceivePort"),
ReceivePort,
FilePath
);
Result = GConfig->GetString(
TEXT("NetReceive"),
TEXT("ReceiveIP"),
ReceiveIP,
FilePath
);
UE_LOG(LogTemp, Log, TEXT("AUDPReceiverActor::BeginPlay nReceiveFlag=%d"), nReceiveFlag);
/*if (1 == nReceiveFlag)
{
Start(ReceiveIP, ReceivePort);
}*/
if (2 == NetType)
{
Start(ReceiveIP, ReceivePort);
}
}
// Called every frame
void AUDPReceiverActor::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
void AUDPReceiverActor::EndPlay(const EEndPlayReason::Type EndPlayReason)
{
Super::EndPlay(EndPlayReason);
delete UDPReceiver;
UDPReceiver = nullptr;
if (ReceiveSocket)
{
ReceiveSocket->Close();
ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->DestroySocket(ReceiveSocket);
ReceiveSocket = nullptr;
}
}
bool AUDPReceiverActor::Start(const FString TheIP, const int32 ThePort)
{
// Create Socket
// FIPv4Endpoint Endpoint(FIPv4Address(0, 0, 0, 0), ThePort);
//接收固定IP和端口 消息 begin
//FString TheIP = TEXT("192.168.50.5");
//FIPv4Address Addr;
//FIPv4Address::Parse(TheIP, Addr);
//FIPv4Endpoint Endpoint(Addr, ThePort);
//接收固定IP和端口 消息 begin
FIPv4Endpoint Endpoint(FIPv4Address::Any, ThePort);//所有ip地址本地 FIPv4Address::Any FIPv4Address::InternalLoopback FIPv4Address::LanBroadcast
/*FIPv4Address Addr;
FIPv4Address::Parse(TheIP, Addr);
FIPv4Endpoint Endpoint(Addr, ThePort);*/
//BUFFER SIZE
int32 BufferSize = 2 * 1024 * 1024;
ReceiveSocket = FUdpSocketBuilder(TEXT("UdpSocketBuilderSocket"))
.AsNonBlocking()
.AsReusable()
.BoundToEndpoint(Endpoint)
.WithReceiveBufferSize(BufferSize);
ReceiveSocket->SetSendBufferSize(BufferSize, BufferSize);
ReceiveSocket->SetReceiveBufferSize(BufferSize, BufferSize);
FTimespan ThreadWaitTime = FTimespan::FromMilliseconds(100);
UDPReceiver = new FUdpSocketReceiver(ReceiveSocket, ThreadWaitTime, TEXT("UdpSocketReceiverThread"));
UDPReceiver->OnDataReceived().BindUObject(this, &AUDPReceiverActor::Recv);
UDPReceiver->Start();
return true;
}
void AUDPReceiverActor::Recv(const FArrayReaderPtr& ArrayReader, const FIPv4Endpoint& Endpoint)
{
if (ArrayReader.IsValid())
{
FArrayReader* pArrayReade = ArrayReader.Get();
uint8 data[1024];
FMemory::Memzero(data, 1024);
FMemory::Memcpy(data, pArrayReade->GetData(), pArrayReade->Num());
FString strData = ((const char*)data);
if (!strData.IsEmpty())
{
UE_LOG(LogTemp, Log, TEXT("AUDPReceiverActor::Recv strData=%s"), *strData);
if (pArrayReade->TotalSize() == sizeof(FMessageDefinition))
{
FMessageDefinition* pData = (FMessageDefinition*)pArrayReade->GetData();
MessageData = *pData;
std::string strName;
strName = MessageData.name;
FString CurName(UTF8_TO_TCHAR(strName.c_str()));
UE_LOG(LogTemp, Log, TEXT("AUDPReceiverActor::Recv CurName=%s"), *CurName);
UE_LOG(LogTemp, Log, TEXT("AUDPReceiverActor::Recv MessageData.x=%f"), MessageData.x);
}
}
}
}
3、读取配置文件获取IP和端口
?4、把AUDPReceiverActor、AUDPSenderActor摆放到场景地图,命令启动两个客户端测试
5、xxx.Build.cs文件,如下
|