UE4修改自Rama的UDP通信蓝图插件
UE4.15没有提供蓝图UDP的组件,可以在网上找到一个ID叫Rama写的源代码,我把它封装成插件了(MyUdpPlugin),方便在各个UE4版本工程中使用UDP通信。
使用方式:
1、在自己的工程根目录下新建一个Plugins文件夹,将MyUdpPlugin拷贝进去
2、一般情况下需要重新编译一下插件,最终你会得到一个插件的dll
3、新建一个蓝图类。接收UDP信息就选择MyUDPReceiver,发送UDP就选择MyUDPSender,这两个类都继承自Actor
4、将新建的蓝图类拖拽一个实例到关卡蓝图中
5、编辑蓝图。可以使用网络调试助手调试通信是否成功。
关于ListenPort,RemotePort和RemoteIP,如果在工程打包以后想改变,可以手动添加配置文件,在配置文件中修改
以下是插件源代码
MyUdpPlugin.uplugin
{
"FileVersion": ,
"Version": ,
"VersionName": "1.0",
"FriendlyName": "MyUdpPlugin",
"Description": "",
"Category": "Other",
"CreatedBy": "",
"CreatedByURL": "",
"DocsURL": "",
"MarketplaceURL": "",
"SupportURL": "",
"CanContainContent": true,
"IsBetaVersion": false,
"Installed": false,
"Modules": [
{
"Name": "MyUdpPlugin",
"Type": "Runtime",
"LoadingPhase": "PreLoadingScreen"
}
]
}
MyUdpPlugin.Build.cs
// Some copyright should be here... using UnrealBuildTool; public class MyUdpPlugin : ModuleRules
{
public MyUdpPlugin(TargetInfo Target)
{ PublicIncludePaths.AddRange(
new string[] {
"MyUdpPlugin/Public" // ... add public include paths required here ...
}
); PrivateIncludePaths.AddRange(
new string[] {
"MyUdpPlugin/Private", // ... add other private include paths required here ...
}
); PublicDependencyModuleNames.AddRange(
new string[]
{
"Core",
// ... add other public dependencies that you statically link with here ...
}
); PrivateDependencyModuleNames.AddRange(
new string[]
{
"CoreUObject",
"Engine",
"Slate",
"SlateCore",
"Sockets", "Networking"
// ... add private dependencies that you statically link with here ...
}
); DynamicallyLoadedModuleNames.AddRange(
new string[]
{
// ... add any modules that your module loads dynamically here ...
}
);
}
}
MyUdpPlugin.h
// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. #pragma once #include "ModuleManager.h" class FMyUdpPluginModule : public IModuleInterface
{
public: /** IModuleInterface implementation */
virtual void StartupModule() override;
virtual void ShutdownModule() override;
};
MyUdpPlugin.cpp
// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. #include "MyUdpPlugin.h" #define LOCTEXT_NAMESPACE "FMyUdpPluginModule" void FMyUdpPluginModule::StartupModule()
{
// This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module } void FMyUdpPluginModule::ShutdownModule()
{
// This function may be called during shutdown to clean up your module. For modules that support dynamic reloading,
// we call this function before unloading the module. } #undef LOCTEXT_NAMESPACE IMPLEMENT_MODULE(FMyUdpPluginModule, MyUdpPlugin)
MyUDPReceiver.h
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "Networking.h"
//#include "AnyCustomData.h"//如果发送、接收方都是UE4,可以使用FArchive对传输数据进行序列化与反序列化
#include "GameFramework/Actor.h"
#include "Engine.h"
#include "MyUDPReceiver.generated.h" UCLASS()
class AMyUDPReceiver : public AActor
{
GENERATED_BODY() public:
// Sets default values for this actor's properties
AMyUDPReceiver(); protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override; public:
// Called every frame
virtual void Tick(float DeltaTime) override; /** Data has been received!! */
UFUNCTION(BlueprintImplementableEvent, Category = "MyUDPSender")
void DataReceived(const TArray<uint8>& rawData, const FString& tryToString); FSocket* ListenSocket; FUdpSocketReceiver* UDPReceiver = nullptr;
void Recv(const FArrayReaderPtr& ArrayReaderPtr, const FIPv4Endpoint& EndPt); /*
* Trying read ListenPort parameter from GameIni config, if ListenPort!=0,
* the parameter ListenPort will be overridden.
* You can config them in YourProject\Config\DefaultGame.ini or
* YourPackagedProject\Saved\Config\WindowsNoEditor\Game.ini.
* [MyUDP]
* ListenPort=2016
*/
UFUNCTION(BlueprintCallable, Category = "MyUDPSender")
bool StartUDPReceiver(const FString& YourChosenSocketName, int32 ListenPort = ); UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MyUDPSender")
bool ShowOnScreenDebugMessages; //ScreenMsg
FORCEINLINE void ScreenMsg(const FString& Msg)
{
if (!ShowOnScreenDebugMessages) return;
GEngine->AddOnScreenDebugMessage(-, .f, FColor::Red, *Msg);
}
FORCEINLINE void ScreenMsg(const FString& Msg, const int32 Value)
{
if (!ShowOnScreenDebugMessages) return;
GEngine->AddOnScreenDebugMessage(-, .f, FColor::Red, FString::Printf(TEXT("%s %d"), *Msg, Value));
}
FORCEINLINE void ScreenMsg(const FString& Msg, const int32 Value, const FString& Msg2)
{
if (!ShowOnScreenDebugMessages) return;
GEngine->AddOnScreenDebugMessage(-, .f, FColor::Red, FString::Printf(TEXT("%s %d %s"), *Msg, Value, *Msg2));
}
/** Called whenever this actor is being removed from a level */
virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
};
MyUDPReceiver.cpp
#include "MyUdpPlugin.h" #include "MyUDPReceiver.h"
#include <string> // Sets default values
AMyUDPReceiver::AMyUDPReceiver()
{
// 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; ListenSocket = NULL;
ShowOnScreenDebugMessages = true;
} // Called when the game starts or when spawned
void AMyUDPReceiver::BeginPlay()
{
Super::BeginPlay(); } // Called every frame
void AMyUDPReceiver::Tick(float DeltaTime)
{
Super::Tick(DeltaTime); } void AMyUDPReceiver::EndPlay(const EEndPlayReason::Type EndPlayReason)
{
Super::EndPlay(EndPlayReason); delete UDPReceiver;
UDPReceiver = nullptr; //Clear all sockets!
//makes sure repeat plays in Editor don't hold on to old sockets!
if (ListenSocket)
{
ListenSocket->Close();
ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->DestroySocket(ListenSocket);
}
} //Start UDP Receiver
bool AMyUDPReceiver::StartUDPReceiver(const FString& YourChosenSocketName, int32 ListenPort)
{
int32 listenPortFromGameIni = ;
GConfig->GetInt(TEXT("MyUDP"), TEXT("ListenPort"), listenPortFromGameIni, GGameIni);
//ScreenMsg(GGameIni);
ScreenMsg("ListenPort From Game.ini: [MyUDP] ListenPort=", listenPortFromGameIni);
if (listenPortFromGameIni!=)
{
ListenPort = listenPortFromGameIni;
} //Create Socket
FIPv4Endpoint Endpoint(FIPv4Address::Any, ListenPort); //BUFFER SIZE
int32 BufferSize = * * ; ListenSocket = FUdpSocketBuilder(*YourChosenSocketName)
.AsNonBlocking()
.AsReusable()
.BoundToEndpoint(Endpoint)
.WithReceiveBufferSize(BufferSize);
; FTimespan ThreadWaitTime = FTimespan::FromMilliseconds();
UDPReceiver = new FUdpSocketReceiver(ListenSocket, ThreadWaitTime, TEXT("UDP RECEIVER"));
UDPReceiver->OnDataReceived().BindUObject(this, &AMyUDPReceiver::Recv); UDPReceiver->Start(); ScreenMsg("UDP Receiver Initialized Successfully!!!");
return true;
} void AMyUDPReceiver::Recv(const FArrayReaderPtr& ArrayReaderPtr, const FIPv4Endpoint& EndPt)
{
//FAnyCustomData Data;
//*ArrayReaderPtr << Data; //Now de-serializing! See AnyCustomData.h
//BPEvent_DataReceived(Data); //BP Event int32 dataByteNum = ArrayReaderPtr->Num();
TArray<uint8> ReceivedData;
for (int i = ; i < dataByteNum; i++)
{
uint8 tmp;
*ArrayReaderPtr << tmp;
ReceivedData.Add(tmp);
}
ReceivedData.Add('\0');
FString tryToString(reinterpret_cast<const char*>(ReceivedData.GetData()));
ReceivedData.RemoveSingle('\0');
ScreenMsg("Received from " + EndPt.ToString() + ", Received bytes = ", dataByteNum, ", Received String =" + tryToString);
DataReceived(ReceivedData, tryToString);
}
MyUDPSender.h
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "Networking.h"
#include "GameFramework/Actor.h"
#include "MyUDPSender.generated.h" UCLASS()
class AMyUDPSender : public AActor
{
GENERATED_BODY() public:
// Sets default values for this actor's properties
AMyUDPSender(); protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override; public:
// Called every frame
virtual void Tick(float DeltaTime) override; UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MyUDPSender")
bool ShowOnScreenDebugMessages; TSharedPtr<FInternetAddr> RemoteAddr;
FSocket* SenderSocket; UFUNCTION(BlueprintCallable, Category = "MyUDPSender")
bool SendString(FString ToSend); /*
* Trying read parameters from GameIni config, if RemoteIP!="" or RemotePort!=0,
* the two parameters(RemoteIP and RemotePort) will be overridden.
* You can config them in YourProject\Config\DefaultGame.ini or
* YourPackagedProject\Saved\Config\WindowsNoEditor\Game.ini.
* [MyUDP]
* RemoteIP=192.168.1.117
* RemoterPort=2016
*/
UFUNCTION(BlueprintCallable, Category = "MyUDPSender")
bool StartUDPSender(const FString& YourChosenSocketName,
FString RemoteIP="127.0.0.1",int32 RemotePort=); //ScreenMsg
FORCEINLINE void ScreenMsg(const FString& Msg)
{
if (!ShowOnScreenDebugMessages) return;
GEngine->AddOnScreenDebugMessage(-, .f, FColor::Red, *Msg);
}
FORCEINLINE void ScreenMsg(const FString& Msg, const int32 Value)
{
if (!ShowOnScreenDebugMessages) return;
GEngine->AddOnScreenDebugMessage(-, .f, FColor::Red, FString::Printf(TEXT("%s %d"), *Msg, Value));
}
FORCEINLINE void ScreenMsg(const FString& Msg, const int32 Value, const FString& Msg2)
{
if (!ShowOnScreenDebugMessages) return;
GEngine->AddOnScreenDebugMessage(-, .f, FColor::Red, FString::Printf(TEXT("%s %d %s"), *Msg, Value, *Msg2));
} /** Called whenever this actor is being removed from a level */
virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
};
MyUDPSender.cpp
#include "MyUdpPlugin.h" //#include "AnyCustomData.h"//如果发送、接收方都是UE4,可以使用FArchive对传输数据进行序列化与反序列化
#include "MyUDPSender.h"
#include <string>
#include "StringConv.h" // Sets default values
AMyUDPSender::AMyUDPSender()
{
// 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; SenderSocket = NULL;
ShowOnScreenDebugMessages = true;
} // Called when the game starts or when spawned
void AMyUDPSender::BeginPlay()
{
Super::BeginPlay(); } // Called every frame
void AMyUDPSender::Tick(float DeltaTime)
{
Super::Tick(DeltaTime); } void AMyUDPSender::EndPlay(const EEndPlayReason::Type EndPlayReason)
{
Super::EndPlay(EndPlayReason); if (SenderSocket)
{
SenderSocket->Close();
ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->DestroySocket(SenderSocket);
}
} bool AMyUDPSender::StartUDPSender(
const FString& YourChosenSocketName,
FString RemoteIP /*= "127.0.0.1"*/, int32 RemotePort /*= 2017*/
)
{
FString remoteIPFromGameIni = TEXT("");
int32 remotePortFromGameIni = ;
GConfig->GetString(TEXT("MyUDP"), TEXT("RemoteIP"), remoteIPFromGameIni, GGameIni);
GConfig->GetInt(TEXT("MyUDP"), TEXT("RemotePort"), remotePortFromGameIni, GGameIni);
//ScreenMsg(GGameIni);
ScreenMsg("RemoteAddress From Game.ini: [MyUDP] RemoteIP="+ remoteIPFromGameIni +", RemotePort=", remotePortFromGameIni);
if (!remoteIPFromGameIni.IsEmpty())
{
RemoteIP = remoteIPFromGameIni;
}
if (remotePortFromGameIni!=)
{
RemotePort = remotePortFromGameIni;
} //Create Remote Address.
RemoteAddr = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateInternetAddr(); bool bIsValid;
RemoteAddr->SetIp(*RemoteIP, bIsValid);
RemoteAddr->SetPort(RemotePort); if (!bIsValid)
{
ScreenMsg("IP address was not valid!" + RemoteIP);
return false;
} SenderSocket = FUdpSocketBuilder(*YourChosenSocketName)
.AsReusable()
.WithBroadcast()
; //check(SenderSocket->GetSocketType() == SOCKTYPE_Datagram); //Set Send Buffer Size
int32 SendSize = * * ;
SenderSocket->SetSendBufferSize(SendSize, SendSize);
SenderSocket->SetReceiveBufferSize(SendSize, SendSize); ScreenMsg("UDP Sender Initialized Successfully!!!");
return true;
} bool AMyUDPSender::SendString(FString ToSend)
{
if (!SenderSocket)
{
ScreenMsg("No sender socket");
return false;
} int32 BytesSent = ; //FAnyCustomData NewData;
//NewData.Scale = FMath::FRandRange(0, 1000);
//NewData.Count = FMath::RandRange(0, 100);
//NewData.Color = FLinearColor(FMath::FRandRange(0, 1), FMath::FRandRange(0, 1), FMath::FRandRange(0, 1), 1);
//FArrayWriter Writer;
//Writer << NewData; //Serializing our custom data, thank you UE4!
//SenderSocket->SendTo(Writer.GetData(), Writer.Num(), BytesSent, *RemoteAddr); TCHAR* pSendData = ToSend.GetCharArray().GetData();
int32 nDataLen = FCString::Strlen(pSendData);
uint8* dst = (uint8*)TCHAR_TO_UTF8(pSendData);
SenderSocket->SendTo(dst, nDataLen, BytesSent, *RemoteAddr); if (BytesSent <= )
{
const FString Str = "Socket is valid but the sender sent 0 bytes!";
UE_LOG(LogTemp, Error, TEXT("%s"), *Str);
ScreenMsg(Str);
return false;
} ScreenMsg("UDP Send Success! Bytes Sent = ", BytesSent, ", ToSend String =" + ToSend+", To "+ RemoteAddr->ToString(true)); return true;
}
AnyCustomData.h
// Fill out your copyright notice in the Description page of Project Settings. #pragma once
#include "AnyCustomData.generated.h" USTRUCT(BlueprintType)
struct FAnyCustomData
{
GENERATED_USTRUCT_BODY() UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Joy Color")
FString Name = "Victory!"; UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Joy Color")
int32 Count = ; UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Joy Color")
float Scale = .f; UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Joy Color")
FLinearColor Color = FLinearColor::Red; FAnyCustomData() {};
~FAnyCustomData() {};
};
FORCEINLINE FArchive& operator<<(FArchive &Ar, FAnyCustomData& TheStruct)
{
Ar << TheStruct.Name;
Ar << TheStruct.Count;
Ar << TheStruct.Scale;
Ar << TheStruct.Color; return Ar;
}
UE4修改自Rama的UDP通信蓝图插件的更多相关文章
- 高性能 TCP & UDP 通信框架 HP-Socket v3.3.1
HP-Socket 是一套通用的高性能 TCP/UDP 通信框架,包含服务端组件.客户端组件和 Agent 组件,广泛适用于各种不同应用场景的 TCP/UDP 通信系统,提供 C/C++.C#.Del ...
- 高性能 TCP & UDP 通信框架 HP-Socket v3.2.3
HP-Socket 是一套通用的高性能 TCP/UDP 通信框架,包含服务端组件.客户端组件和 Agent 组件,广泛适用于各种不同应用场景的 TCP/UDP 通信系统,提供 C/C++.C#.Del ...
- 高性能 TCP & UDP 通信框架 HP-Socket v3.2.2 正式发布
HP-Socket 是一套通用的高性能 TCP/UDP 通信框架,包含服务端组件.客户端组件和 Agent 组件,广泛适用于各种不同应用场景的 TCP/UDP 通信系统,提供 C/C++.C#.Del ...
- QT之UDP通信
前言:前一篇讲了TCP通信,这篇来看看UDP通信. 这里说明一下,UDP通信中分为三种通信分别为单播.组播和广播,下面将一一为大家介绍. 同样的我们都需要在工程文件中添加network QT += c ...
- 【RL-TCPnet网络教程】第17章 RL-TCPnet之UDP通信
第17章 RL-TCPnet之UDP通信 本章节为大家讲解RL-TCPnet的UDP通信实现,学习本章节前,务必要优先学习第16章UDP用户数据报协议基础知识.有了这些基础知识之后,再搞本章 ...
- Java入门网络编程-使用UDP通信
程序说明: 以下代码,利用java的网络编程,使用UDP通信作为通信协议,描述了一个简易的多人聊天程序,此程序可以使用公网或者是局域网进行聊天,要求有一台服务器.程序一共分为2个包,第一个包:udp, ...
- 高性能 TCP & UDP 通信框架 HP-Socket v3.5.3
HP-Socket 是一套通用的高性能 TCP/UDP 通信框架,包含服务端组件.客户端组件和 Agent 组件,广泛适用于各种不同应用场景的 TCP/UDP 通信系统,提供 C/C++.C#.Del ...
- 高性能 TCP & UDP 通信框架 HP-Socket v3.5.2
HP-Socket 是一套通用的高性能 TCP/UDP 通信框架,包含服务端组件.客户端组件和 Agent 组件,广泛适用于各种不同应用场景的 TCP/UDP 通信系统,提供 C/C++.C#.Del ...
- 高性能 TCP & UDP 通信框架 HP-Socket v3.5.1
HP-Socket 是一套通用的高性能 TCP/UDP 通信框架,包含服务端组件.客户端组件和 Agent 组件,广泛适用于各种不同应用场景的 TCP/UDP 通信系统,提供 C/C++.C#.Del ...
随机推荐
- sqlserver 多排序的问题
sql 执行默认执行排序的第一个字段,如果结果集中含有重复的列的字段,才会按照2...N个字段进行排序,没有重复列多排序无效果
- 一款基于javascript的3D玻璃破碎特效
之前为大家介绍了一款 html5 canvas实现图片玻璃碎片特效.今天要给大家带来一款基于javascript的3D玻璃破碎特效.效果图如下: 在线预览 源码下载 html代码: <div ...
- 浅析js前端发展及mvvm的选型
最近终于下定决心学点前端的东西,然而各种框架,让人眼花缭乱. 先总结一下js前端的发展史 1.刀耕火种,原始时代 这个时候用DOM原生API来操html元素,估计getElementBy之类的函数满天 ...
- java 支付宝wap支付初识
最近突然想弄下支付宝的支付,因为感觉很好玩.中间遇到很多问题,查查找找,总算是整了两天给整出来了,这里为自己记录下. 第一步:直接去安卓支付宝的官方文档去,写的很清楚了已经,这里有源码https:// ...
- USB 转LAN AX88772B 模块驱动添加记录
使用 AX88772B 模块进行扩展百兆网口. 资料地址: http://www.asix.com.tw/cs/products.php?op=pItemdetail&PItemID=105; ...
- /dev/null脚本中作用
/dev/null设备文件只有一个作用,往它里面写任何数据都直接丢弃. 因此保证了该命令执行时屏幕上没有任何输出. 在shell中常见. command > /dev/null 2> ...
- kafkaStream解析json出错导致程序中断的解决方法
出错在 KStreamFlatMapValues 方法执行时,由于json异常数据无法解析,结果生成的值为null,报错信息如下: 2018-04-18 19:21:04,776 ERROR [app ...
- JVM中的垃圾回收
GC 垃圾回收回收什么 Java的内存分配原理与C/C++不同.C/C++每次申请内存时都要malloc进行系统调用.而系统调用发生在内核空间,每次都要中断进行切换,这须要一定的开销. 而Java虚拟 ...
- Linq中的ToList()和CopyToDataTable()
最近在项目中使用了Linq,想把Linq的查询结果直接转换成DataTable对象,通过查找发现Linq有一个CopyToDataTable<T>的泛型方法,该方法只能在T是DataRow ...
- 初学 Spring boot 报错 Whitelabel Error Page 404
按照教程,写了个最简单的 HelloWorld,尼玛报错 -->Whitelabel Error Page 404. 网上99%都是项目结构不对,说什么 Application放在父级 pack ...