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 ...
随机推荐
- Django 用ModelForm批量保存form表单(非常实用的方法) mfor_verity项目
1.先看一下 Model 非常多 from django.db import models from users.models import UserProfile # Create your mod ...
- ANSI文件操作
ANSI文件操作 在ANSI C中,对文件的操作分为两种方式,即流式文件操作和I/O文件操作,下面就分别介绍之. 一.流式文件操作 这种方式的文件操作有一个重要的结构FILE,FILE在stdio.h ...
- UTF-8以字节为单位对Unicode进行编码
UTF-8以字节为单位对Unicode进行编码.从Unicode到UTF-8的编码方式如下: Unicode编码(16进制) UTF-8 字节流(二进制) 000000 - 00007F 0xxxxx ...
- 文件服务器和web应用分离的思路(转)
目前在做一个应用,有不同的客户端,包括web应用的客户端,其他的客户端,都要访问我的文件服务器,通过文件服务程序提供的服务来访问文件,但是对文件管理服务器这个应用,没有什么思路,请大家给点思路,谢谢: ...
- C#捕获鼠标消息
在C#中怎样禁用鼠标按键,我们可以通过ImessageFilter接口下的PreFilterMessage方法.Application类的AddMessageFilter方法,RemoveMessag ...
- Intellij IDEA 部署 项目在tomcat 原理
https://www.zhihu.com/question/54757013 Intellij IDEA通过tomcat部署web项目的机制 IntelliJ IDEA通过Tomcat启动项目过程分 ...
- vmware下ubuntu不能上网 => 恢复默认虚拟网络
1.关闭虚拟机ubuntu 2.打开:编辑=> 虚拟网络编辑器 3.打开后点击左下角恢复默认 4.重启ubuntu就可以了
- json拼接转义符
//转义符替 function escapeReplace(Str) { var newStrJson = Str.replace(/\%/g, "%25"); newStrJso ...
- 使用特殊构造的5GB文件测试Win2012Dedup功能
WinServer2012一个崭新的功能就是支持重复数据删除功能.为了测试这个功能的情况,特别构造了一个特殊的5GB文件用于此次测试.惯例,先说下测试环境的搭建1 使用ESXi5上的版本8的VM,安装 ...
- informatica中的workflow连接远程数据库
如果是远程oracle这样写 名称随便起,方便自己记住,后面用户名密码你都知道,再加上数据库的地址:端口/SID就可以了. 如10.33.2.208:1521/torcl