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 ...
随机推荐
- android 使用 sqlite
SQLiteHelper .class (升级的时候,做点小技巧) package com.keyue.qlm.util; import android.content.Context; imp ...
- thrift学习之二----学习资料积累
自己没有仔细安装,从网上搜的安装技术文章,在此做个备份,以防后面用到: http://blog.csdn.net/hshxf/article/details/5567019 http://blog.c ...
- 一站式学习Wireshark(一):Wireshark基本用法
按照国际惯例,从最基本的说起. 抓取报文: 下载和安装好Wireshark之后,启动Wireshark并且在接口列表中选择接口名,然后开始在此接口上抓包.例如,如果想要在无线网络上抓取流量,点击无线接 ...
- kafkaStream解析json出错导致程序中断的解决方法
出错在 KStreamFlatMapValues 方法执行时,由于json异常数据无法解析,结果生成的值为null,报错信息如下: 2018-04-18 19:21:04,776 ERROR [app ...
- DataGridView使用技巧五:自动设定列宽和行高
一.设定行高和列宽自动调整 设定包括Header和所有单元格的列宽自动调整 //设置包括Header和所有单元格的列宽自动调整 this.dgv_PropDemo.AutoSizeColumnsMod ...
- Ajax-jQuery_Ajax_实例 ($.ajax、$.post、$.get)
Jquery在异步提交方面封装的很好,直接用AJAX非常麻烦,Jquery大大简化了我们的操作,不用考虑浏览器的诧异了. 推荐一篇不错的jQuery Ajax 实例文章,忘记了可以去看看, 地址为:h ...
- easyUI datagrid 排序
easyUI datagrid 排序 1.首先设置datagrid属性sortName 2.设置sortOrder 3.设置remoteSort(注:此属性默认为true,如果如果是对本地数据排序必须 ...
- WordCount示例深度学习MapReduce过程
转自: http://blog.csdn.net/yczws1/article/details/21794873 . 我们都安装完Hadoop之后,按照一些案例先要跑一个WourdCount程序,来测 ...
- C++ 判断目录是否存在并新建目录
http://blog.csdn.net/u012005313/article/details/50688257 #include <io.h> #include <string&g ...
- linux gzip 命令详解
减少文件大小有两个明显的好处,一是可以减少存储空间,二是通过网络传输文件时,可以减少传输的时间.gzip是在Linux系统中经常使用的一个对文件进行压缩和解压缩的命令,既方便又好用. 语法:gzip ...