UE4 UDP通信

    xiaoxiao2021-03-25  203

    用c++创建两个Actor类,分别为UDPSend(发送)   和  UDPRecive(接收)

    代码如下:

    UDPSend.h

    // Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "Networking.h" #include "GameFramework/Actor.h" #include "UDPSend.generated.h" UCLASS() class UDP_API AUDPSend : public AActor { GENERATED_BODY() public: // Sets default values for this actor's properties AUDPSend(); // Called when the game starts or when spawned virtual void BeginPlay() override; // Called every frame virtual void Tick( float DeltaSeconds ) override; public: bool IsUDP; UFUNCTION(BlueprintCallable, Category = "UDP") bool RamaUDPSender_SendString(FString ToSend); public: TSharedPtr<FInternetAddr> RemoteAddr; FSocket* SenderSocket; UFUNCTION(BlueprintCallable, Category = "UDP") bool StartUDPSender(const FString& YourChosenSocketName, const FString& TheIP, const int32 ThePort, bool UDP); public: UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "UDP") bool ShowOnScreenDebugMessages; //ScreenMsg FORCEINLINE void ScreenMsg(const FString& Msg) { if (!ShowOnScreenDebugMessages) return; GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, *Msg); } FORCEINLINE void ScreenMsg(const FString& Msg, const float Value) { if (!ShowOnScreenDebugMessages) return; GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("%s %f"), *Msg, Value)); } FORCEINLINE void ScreenMsg(const FString& Msg, const FString& Msg2) { if (!ShowOnScreenDebugMessages) return; GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("%s %s"), *Msg, *Msg2)); } public: /** Called whenever this actor is being removed from a level */ virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override; };

    UDPSend.cpp

    // Fill out your copyright notice in the Description page of Project Settings. #include "UDP.h" #include "UDPSend.h" // Sets default values AUDPSend::AUDPSend() { // 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 AUDPSend::BeginPlay() { Super::BeginPlay(); } // Called every frame void AUDPSend::Tick( float DeltaTime ) { Super::Tick( DeltaTime ); } void AUDPSend::EndPlay(const EEndPlayReason::Type EndPlayReason) { Super::EndPlay(EndPlayReason); //~~~~~~~~~~~~~~~~ if (SenderSocket) //Clear all sockets! { SenderSocket->Close(); ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->DestroySocket(SenderSocket); } } bool AUDPSend::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; } bool AUDPSend::StartUDPSender(const FString & YourChosenSocketName, const FString & TheIP, const int32 ThePort, bool UDP)///初始化远端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; }

    UDPRecive.h

    // Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "Networking.h" #include "GameFramework/Actor.h" #include "UDPRecive.generated.h" UCLASS() class UDP_API AUDPRecive : public AActor { GENERATED_BODY() public: // Sets default values for this actor's properties AUDPRecive(); // Called when the game starts or when spawned virtual void BeginPlay() override; // Called every frame virtual void Tick( float DeltaSeconds ) override; public: FSocket* ListenSocket; FUdpSocketReceiver* UDPReceiver = nullptr; UFUNCTION(BlueprintCallable, Category = "UDP") void StartUDPReceiver(const FString& YourChosenSocketName, const FString& TheIP, const int32 ThePort, bool& success); UFUNCTION(BlueprintPure, Category = "UDP") void DataRecv(FString& str, bool& success); //ScreenMsg FORCEINLINE void ScreenMsg(const FString& Msg) { GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, *Msg); } FORCEINLINE void ScreenMsg(const FString& Msg, const float Value) { GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("%s %f"), *Msg, Value)); } FORCEINLINE void ScreenMsg(const FString& Msg, const FString& Msg2) { GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("%s %s"), *Msg, *Msg2)); } public: /** Called whenever this actor is being removed from a level */ virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override; };

    UDPRecive.cpp

    // Fill out your copyright notice in the Description page of Project Settings. #include "UDP.h" #include "UDPRecive.h" // Sets default values AUDPRecive::AUDPRecive() { // 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; } // Called when the game starts or when spawned void AUDPRecive::BeginPlay() { Super::BeginPlay(); } // Called every frame void AUDPRecive::Tick( float DeltaTime ) { Super::Tick( DeltaTime ); } void AUDPRecive::EndPlay(const EEndPlayReason::Type EndPlayReason) { Super::EndPlay(EndPlayReason); //~~~~~~~~~~~~~~~~ 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); } } //Start UDP Receiver void AUDPRecive::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; } void AUDPRecive::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; } //return success; } 最后在Bulid.cs里面增加如下代码:

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

    然后把工程文件关闭重新生成一下,这个是解决Networking报错的方法。

    接着用蓝图继承以上两个类,在蓝图里调用C++开放的方法,拖入场景进行实例化。

    参考:https://wiki.unrealengine.com/UDP_Socket_Sender_Receiver_From_One_UE4_Instance_To_Another

    转载请注明原文地址: https://ju.6miu.com/read-1171.html

    最新回复(0)