UE UDP通信

发布于:2025-08-17 ⋅ 阅读:(11) ⋅ 点赞:(0)

1.确保工程为C++工程,在项目工程的xx.Build.cs中加入Networking和Sockets模块。

PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "Networking", "Sockets"});

2.C++创建Actor,命名为UDPClient。

3.编写代码UDPClient.h和UDPClient.cpp实现UDP发送和接收功能。

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Runtime/Sockets/Public/Sockets.h"
#include "Sockets/Public/SocketSubsystem.h"
#include "Runtime/Networking/Public/Common/UdpSocketBuilder.h"
#include "Runtime/Networking/Public/Common/UdpSocketReceiver.h"
#include "Networking/Public/Interfaces/IPv4/IPv4Address.h"
#include "UDPClient.generated.h"

UCLASS()
class MYBLANK_API AUDPClient : public AActor
{
	GENERATED_BODY()
	
public:	
	// Sets default values for this actor's properties
	AUDPClient();

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;

public:

	FSocket* udpSocket;
	//远程的地址
	TSharedPtr<FInternetAddr> RemoteAddr;
	
	UFUNCTION(BlueprintCallable, Category = "UDP")
	bool CreateUdp(const FString& socketName, const FString& targetIP, const int32 targetPort, const int32 selfPort);
	
	UFUNCTION(BlueprintCallable, Category = "UDP")
	bool SendMsg(FString msg);
	
	UFUNCTION(BlueprintCallable, Category = "UDP")
	void RecvMsg(bool& result, FString& msg);

};
// Fill out your copyright notice in the Description page of Project Settings.


#include "UDPClient.h"

// Sets default values
AUDPClient::AUDPClient()
{
 	// 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;
	udpSocket = NULL;
}

// Called when the game starts or when spawned
void AUDPClient::BeginPlay()
{
	Super::BeginPlay();
	
}

// Called every frame
void AUDPClient::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

}

void AUDPClient::EndPlay(const EEndPlayReason::Type EndPlayReason)
{
	Super::EndPlay(EndPlayReason);
	if (udpSocket)
	{
		udpSocket->Close();
		ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->DestroySocket(udpSocket);
	}
}

bool AUDPClient::CreateUdp(const FString& socketName, const FString& targetIP, const int32 targetPort, const int32 selfPort)
{
	bool bIsValid;
	RemoteAddr = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateInternetAddr();
	RemoteAddr->SetIp(*targetIP, bIsValid);
	RemoteAddr->SetPort(targetPort);
	if (!bIsValid)
	{
		UE_LOG(LogTemp, Warning, TEXT("CreateUdp>> IP address was not valid! "), *targetIP);
		return false;
	}
	int32 BufferSize = 2 * 1024 * 1024;
	FIPv4Endpoint Endpoint(FIPv4Address::Any, selfPort);  //所有ip地址本地
	udpSocket = FUdpSocketBuilder(*socketName)
		.AsReusable()
		.WithBroadcast() // 广播
		.WithSendBufferSize(BufferSize)
		.AsNonBlocking()
		.BoundToEndpoint(Endpoint)
		.WithReceiveBufferSize(BufferSize);
	udpSocket->SetSendBufferSize(BufferSize, BufferSize);
	udpSocket->SetReceiveBufferSize(BufferSize, BufferSize);
	return bIsValid;
}

bool AUDPClient::SendMsg(FString msg)//发送消息
{
	if (!udpSocket)
	{
		UE_LOG(LogTemp, Warning, TEXT("No udpSocket"));
		return false;
	}
	int32 BytesSent = 0;
	FString serialized = msg;
	TCHAR* serializedChar = serialized.GetCharArray().GetData();
	int32 size = FCString::Strlen(serializedChar);
	int32 sent = 0;
	udpSocket->SendTo((uint8*)TCHAR_TO_UTF8(serializedChar), size, BytesSent, *RemoteAddr);
	if (BytesSent < 0)
	{
		const FString Str = "Socket is valid but the receiver received 0 bytes, make sure it is listening properly!";
		UE_LOG(LogTemp, Error, TEXT("%s"), *Str);
		return false;
	}
	UE_LOG(LogTemp, Warning, TEXT("SendMsg Succcess! INFO msg = %s "), *msg);
	return true;
}

void AUDPClient::RecvMsg(bool& result,FString& msg)//接收消息
{
	if (!udpSocket)
	{
		UE_LOG(LogTemp, Warning, TEXT("No udpSocket"));
		result = false;
	}
	TSharedRef<FInternetAddr> targetAddr = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateInternetAddr();
	TArray<uint8> ReceivedData;//定义一个接收器
	uint32 Size;
	if (udpSocket->HasPendingData(Size))
	{
		result = true;
		msg = "";
		uint8* Recv = new uint8[Size];
		int32 BytesRead = 0;

		ReceivedData.SetNumUninitialized(FMath::Min(Size, 65507u));
		udpSocket->RecvFrom(ReceivedData.GetData(), ReceivedData.Num(), BytesRead, *targetAddr);//创建远程接收地址
		char ansiiData[1024];
		memcpy(ansiiData, ReceivedData.GetData(), BytesRead);//拷贝数据到接收器
		ansiiData[BytesRead] = 0;                            //判断数据结束
		FString debugData = UTF8_TO_TCHAR(ansiiData);         //字符串转换
		msg = debugData;
	}
	else
	{
		result = false;
	}
}


FUdpSocketBuilder Functions介绍:

4.创建基于UDPClient的蓝图BP_MyUDPClient。

5.打开蓝图BP_MyUDPClient实现UDP实例化、发送和接收功能。

6.将蓝图BP_MyUDPClient放入场景中启动实现U3D和UE程序UDP通信。


网站公告

今日签到

点亮在社区的每一天
去签到