在UE4上进行UDP通讯

简介

UE4 版本 : 4.20.3
Visual Studio 版本:2017

在UE4上监听UDP端口与向指定IP与端口发送UDP数据包

先决条件

在xxx.Build.cs 文件中添加以下部分
“Sockets”, “Networking”
修改后:

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

using UnrealBuildTool;

public class AVR_Server : ModuleRules
{
	public AVR_Server(ReadOnlyTargetRules Target) : base(Target)
	{
		PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
	
		PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "Sockets", "Networking" });

		PrivateDependencyModuleNames.AddRange(new string[] {  });

		// Uncomment if you are using Slate UI
		// PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" });
		
		// Uncomment if you are using online features
		// PrivateDependencyModuleNames.Add("OnlineSubsystem");

		// To include OnlineSubsystemSteam, add it to the plugins section in your uproject file with the Enabled attribute set to true
	}
}

代码

首先创建BlueprintFunctionLibrary名为UDPSocketServer

H文件

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

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

#pragma once

#include "CoreMinimal.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "Runtime/Networking/Public/Networking.h"
#include "Engine.h"
#include "UDPSocketServer.generated.h"

/**
 * 
 */
UCLASS()
class AVR_SERVER_API UUDPSocketServer : public UBlueprintFunctionLibrary
{
	GENERATED_BODY()
	
public:	
	UFUNCTION(BlueprintCallable, Category = "UDP")
		//新建初始化Receiver函数
		static void StartUDPReceiver(const FString& YourChosenSocketName, const FString& TheIP, const int32 ThePort, bool& success);
	UFUNCTION(BlueprintCallable, Category = "UDP")
		static bool StartUDPSender(const FString& YourChosenSocketName, const FString& TheIP, const int32 ThePort);
	UFUNCTION(BlueprintCallable, Category = "UDP")
		static void CloseUDPReceiver();
	UFUNCTION(BlueprintCallable, Category = "UDP")
		static void CloseUDPSender();

	UFUNCTION(BlueprintCallable, Category = "UDP")
		static bool RamaUDPSender_SendString(FString ToSend);

	UFUNCTION(BlueprintPure, Category = "UDP")
		//DataRecv返回函数
		static void DataRecv(FString& str, bool& success);

	
};

C文件

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

#include "UDPSocketServer.h"

TSharedPtr<FInternetAddr> RemoteAddr;
FSocket* SenderSocket;


FSocket* ListenSocket;
FUdpSocketReceiver* UDPReceiver = nullptr;



//ScreenMsg
void ScreenMsg(const FString& Msg)
{
	GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, *Msg);
}
void ScreenMsg(const FString& Msg, const float Value)
{
	GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("%s %f"), *Msg, Value));
}
void ScreenMsg(const FString& Msg, const FString& Msg2)
{
	GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("%s %s"), *Msg, *Msg2));
}







void UUDPSocketServer::CloseUDPSender()
{

	if (SenderSocket) //Clear all sockets!
	{
		SenderSocket->Close();
		ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->DestroySocket(SenderSocket);
	}
}


bool UUDPSocketServer::RamaUDPSender_SendString(FString ToSend)                 //发送消息处理
{
	if (!SenderSocket)
	{
		ScreenMsg("No sender socket");
		return false;
	}
	//~~~~~~~~~~~~~~~~
	//发送消息
	int32 BytesSent = 0;
	FString serialized = ToSend;
	TCHAR *serializedChar = serialized.GetCharArray().GetData();
	int32 size = FCString::Strlen(serializedChar);
	int32 sent = 0;
	//SenderSocket->SendTo(Writer.GetData(), Writer.Num(), BytesSent, *RemoteAddr);
	SenderSocket->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);
		ScreenMsg(Str);
		return false;
	}

	ScreenMsg("UDP Send Succcess! INFO Sent = ", ToSend);

	return true;
}

void UUDPSocketServer::DataRecv(FString & str, bool & success)
{
	if (!ListenSocket)
	{
		ScreenMsg("No sender socket");
		success = false;
		//return success;
	}
	TSharedRef<FInternetAddr> targetAddr = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateInternetAddr();
	TArray<uint8> ReceivedData;//定义一个接收器
	uint32 Size;
	if (ListenSocket->HasPendingData(Size))
	{
		success = true;
		str = "";
		uint8 *Recv = new uint8[Size];
		int32 BytesRead = 0;

		ReceivedData.SetNumUninitialized(FMath::Min(Size, 65507u));
		ListenSocket->RecvFrom(ReceivedData.GetData(), ReceivedData.Num(), BytesRead, *targetAddr);//创建远程接收地址
		char ansiiData[1024];
		memcpy(ansiiData, ReceivedData.GetData(), BytesRead);//拷贝数据到接收器
		ansiiData[BytesRead] = 0;                            //判断数据结束
		FString debugData = ANSI_TO_TCHAR(ansiiData);         //字符串转换
		str = debugData;
		// memset(ansiiData,0,1024);//清空 

	}
	else
	{
		success = false;
	}

}



bool UUDPSocketServer::StartUDPSender(const FString & YourChosenSocketName, const FString & TheIP, const int32 ThePort)///初始化远端IP 发送信息前
{
	//FIPv4Endpoint Endpoint(FIPv4Address::Any, 6789);
	//Create Remote Address.
	RemoteAddr = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateInternetAddr();

	bool bIsValid;
	RemoteAddr->SetIp(*TheIP, bIsValid);
	RemoteAddr->SetPort(ThePort);

	if (!bIsValid)
	{
		ScreenMsg("Rama UDP Sender>> IP address was not valid!", TheIP);
		return false;
	}


	SenderSocket = FUdpSocketBuilder(*YourChosenSocketName)
		.AsReusable()
		.WithBroadcast()/广播
		.WithSendBufferSize(2 * 1024 * 1024)
		//.BoundToEndpoint(Endpoint)
		;


	//check(SenderSocket->GetSocketType() == SOCKTYPE_Datagram);

	//Set Send Buffer Size
	int32 SendSize = 2 * 1024 * 1024;
	SenderSocket->SetSendBufferSize(SendSize, SendSize);
	SenderSocket->SetReceiveBufferSize(SendSize, SendSize);
	if (bIsValid)
	{
		bIsValid = true;
	}
	return bIsValid;

}

void UUDPSocketServer::CloseUDPReceiver()
{
	delete UDPReceiver;
	UDPReceiver = nullptr;

	//Clear all sockets!
	//      makes sure repeat plays in Editor dont hold on to old sockets!
	if (ListenSocket)
	{
		ListenSocket->Close();
		ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->DestroySocket(ListenSocket);
	}
}



void UUDPSocketServer::StartUDPReceiver(const FString& YourChosenSocketName, const FString& TheIP, const int32 ThePort, bool& success)
{
	TSharedRef<FInternetAddr> targetAddr = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateInternetAddr();
	FIPv4Address Addr;
	FIPv4Address::Parse(TheIP, Addr);

	//Create Socket
	FIPv4Endpoint Endpoint(FIPv4Address::Any, ThePort);  //所有ip地址本地
														 //FIPv4Endpoint Endpoint(Addr, ThePort);                 //指定ip地址
	ListenSocket = FUdpSocketBuilder(*YourChosenSocketName)
		.AsNonBlocking()
		.AsReusable()
		.BoundToEndpoint(Endpoint)
		.WithReceiveBufferSize(2 * 1024 * 1024)

		;
	//BUFFER SIZE
	int32 BufferSize = 2 * 1024 * 1024;
	ListenSocket->SetSendBufferSize(BufferSize, BufferSize);
	ListenSocket->SetReceiveBufferSize(BufferSize, BufferSize);

	if (!ListenSocket)
	{
		ScreenMsg("No socket");
		success = false;

	}
	if (ListenSocket)
	{
		ScreenMsg("The receiver is initialized");
		success = true;
	}

	//return true;

}

蓝图调用

在这里插入图片描述

存在的问题

不支持发送非ASCII的数据
接收也是一样的,需要发送HEX数据的人自己修改

如果不修改直接接收/发送HEX格式数据 会导致崩溃

  • 10
    点赞
  • 70
    收藏
    觉得还不错? 一键收藏
  • 23
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 23
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值