Communication Between UE4 and a Python UDP Server

Hi there, I’m actually stuck at the step of creating an object referencing to the UDPNetworkingWrapper class. I’ve already compiled the code successfully and I can see the wrapper class in the content browser in the editor, but I cannot find this class when I try to assign a variable type. Could somebody help me out why can this happen, is there anything I missed during the process? Thanks in advance.

Yo,

I just played around with Lyons Den’s code and found out, that two things needed to be changed for me:

  1. I switched creating the socket to the UE method ‘FUdpSocketBuilder’:


		wrapper->MySocket = FUdpSocketBuilder(*SocketName)
			.AsNonBlocking()
			.AsReusable()
			.BoundToEndpoint(Endpoint)
			.WithReceiveBufferSize(2 * 1024 * 1024);


yeah. you need an endpoint and a name for this:



		FString SocketName = TEXT("SocketName");
		FIPv4Endpoint Endpoint(FIPv4Address::Any, 8090);


instead of:
wrapper->MySocket = wrapper->SocketSubsystem->CreateSocket(NAME_DGram, *Description, true);

and 2.

I changed the method ‘StringFromBinaryArray’ to:



FString UUDPNetworkingWrapper::StringFromBinaryArray(TArray<uint8>& BinaryArray)
{
	//const char* cstr(reinterpret_cast<const char*>(BinaryArray.GetData(), BinaryArray.Num()));
	BinaryArray.Add(0); // fist add the termination. Not sure if I need this here, since its unclear if incoming binary-array needs to be 0-exited in the first place
	return FString(ANSI_TO_TCHAR(reinterpret_cast<const char*>(BinaryArray.GetData())));
}


Just in case anybody might look at this here again :smiley:

This is very useful, I ran the python code and its working perfectly, I´m having a real problem when creating the object with the UDPNetworkingWrapper Class, I have no option with that class name. I tried creating a c++ class, copying cpp and h files in several directories of the project, and dragging them to the main project, all with no success. How can I import cpp and header files to to use with BP?

Thanks a lot for your help! :slight_smile:

PS. Im sorry if Im being a total noob but my c++ knowledge is limited to very simple scripts in notepad :frowning: I have never compiled/imported something to UE4 from VStudio.

@navas87 In the Editor, select File > New C++ Class and create a new Object class. Copy/Paste as necessary. Then, in the Level BP, select Class Settings and select your new class from the Parent Class dropdown.

Just saw your question. Hope this helps.

This is the same answer given in beginning but fixed few errors.

Add “Sockets” and “Networking” in your PublicDependencyModuleNames under [ProjectName].Build.cs

Create C++ class (UDPNetworkingWrapper) with Object as base from Unreal Engine

UDPNetworkingWrapper.h



#pragma once

#include "CoreMinimal.h"
#include "UObject/NoExportTypes.h"
#include "Object.h"
#include "Runtime/Networking/Public/Networking.h"
#include "Json.h"
#include <string>
#include "UDPNetworkingWrapper.generated.h"

/**
 *
 */
UCLASS(BlueprintType, Blueprintable)
class UDP_YOLO_API UUDPNetworkingWrapper : public UObject
{
    GENERATED_BODY()

public:
    //////////////////////////////////////////////////////////////////////////
    // Construction

    /**
    * Creates and initializes a new UDPNetworking object.
    *
    * @param Description - The description of the socket for debug purposes.
    * @param SenderSocketName - Name of the sender socket for debug purposes.
    * @param TheIP - IP of the the machine you want to send a message too.
    * @param ThePort - The port of the machine you are trying to talk to.
    * @param BufferSize - The size of the buffer for the socket
    * @param AllowBroadCast - Allow broadcasting on this socket?
    * @param Bound - Bind socket to the ip and port?
    * @param Reusable - Is this socket reusable?
    * @param Blocking - Is this socket blocking other data?
    */
    UFUNCTION(BlueprintPure, Category = "UDPNetworking")
        static UUDPNetworkingWrapper* ConstructUDPWrapper(const FString& Description, const FString& SenderSocketName, const FString& TheIP, const int32 ThePort, const int32 BufferSize,
            const bool AllowBroadcast, const bool Bound, const bool Reusable, const bool Blocking);

    static UUDPNetworkingWrapper* Constructor();

    /**
    * Sends the supplied message
    * @param Message The message to be sent.
    */
    UFUNCTION(BlueprintCallable, Category = "UDPNetworking")
        bool sendMessage(FString Message);

    //////////////////////////////////////////////////////////////////////////
    // Destruction and reset

    /** Destroys all data */
    UFUNCTION(BlueprintCallable, Category = "UDPNetworking")
        void UDPDestructor();

    //// Grab Data
    UFUNCTION(BlueprintCallable, Category = "UDPNetworking")
        bool anyMessages();


    /** Test Look for message */
    UFUNCTION(BlueprintCallable, Category = "UDPNetworking")
        FString GrabWaitingMessage();

    static FString StringFromBinaryArray(const TArray<uint8>&  BinaryArray);

private:

    // Holds the socket we are sending on
    FSocket* SenderSocket;

    // Description for debugging
    FString SocketDescription;

    // Remote Address
    FIPv4Endpoint RemoteEndPoint;
    FIPv4Address RemoteAdress;

    // Socket Subsystem
    ISocketSubsystem* SocketSubsystem;

    //UDPReceiveWorker* myRecieverWorker;
    // The data
    TArray<uint8> ReceivedData;
};


UDPNetworkingWrapper.cpp



#include "UDPNetworkingWrapper.h"

UUDPNetworkingWrapper* UUDPNetworkingWrapper::Constructor()
{
    return (UUDPNetworkingWrapper*)StaticConstructObject_Internal(UUDPNetworkingWrapper::StaticClass());
}

UUDPNetworkingWrapper* UUDPNetworkingWrapper::ConstructUDPWrapper(const FString& Description, const FString& SenderSocketName, const FString& TheIP, const int32 ThePort, const int32 BufferSize,
    const bool AllowBroadcast, const bool Bound, const bool Reusable, const bool Blocking)
{

    UUDPNetworkingWrapper* wrapper = Constructor();

    wrapper->SocketSubsystem = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM);

    TArray<FString> Array;
    TheIP.ParseIntoArray(Array, TEXT("."), true);

    wrapper->RemoteAdress = FIPv4Address(FCString::Atoi(*Array[0]), FCString::Atoi(*Array[1]), FCString::Atoi(*Array[2]), FCString::Atoi(*Array[3]));

    wrapper->RemoteEndPoint = FIPv4Endpoint(wrapper->RemoteAdress, ThePort);

    // First set our socket null
    wrapper->SenderSocket = nullptr;

    if (wrapper->SocketSubsystem != nullptr) // If socket subsytem is good
    {
        wrapper->SenderSocket = wrapper->SocketSubsystem->CreateSocket(NAME_DGram, *Description, true);

        if (wrapper->SenderSocket != nullptr) // Is our socket created
        {
            // Setup the socket
            bool Error = !wrapper->SenderSocket->SetNonBlocking(!Blocking) ||
                !wrapper->SenderSocket->SetReuseAddr(Reusable) ||
                !wrapper->SenderSocket->SetBroadcast(AllowBroadcast) ||
                !wrapper->SenderSocket->SetRecvErr();

            if (!Error)
            {
                if (Bound)
                {
                    Error = !wrapper->SenderSocket->Bind(*wrapper->RemoteEndPoint.ToInternetAddr());
                }
            }

            if (!Error)
            {
                int32 OutNewSize;

                wrapper->SenderSocket->SetReceiveBufferSize(BufferSize, OutNewSize);
                wrapper->SenderSocket->SetSendBufferSize(BufferSize, OutNewSize);
            }

            if (Error)
            {
                GLog->Logf(TEXT("FUdpSocketBuilder: Failed to create the socket %s as configured"), *Description);

                wrapper->SocketSubsystem->DestroySocket(wrapper->SenderSocket);
                wrapper->SenderSocket = nullptr;
            }
        }

    }


    return wrapper;
}

bool UUDPNetworkingWrapper::sendMessage(FString Message)
{
    if (!SenderSocket) return false;

    int32 BytesSent;
    FTimespan waitTime = FTimespan(10);
    TCHAR *serializedChar = Message.GetCharArray().GetData();
    int32 size = FCString::Strlen(serializedChar);
    int32 sent = 0;

    // Send to
    //myRecieverWorker = UDPReceiveWorker::JoyInit(SenderSocket, waitTime);
    bool success = SenderSocket->SendTo((uint8*)TCHAR_TO_UTF8(serializedChar), size, BytesSent, *RemoteEndPoint.ToInternetAddr());
    if (success && BytesSent > 0) // Success
    {
        return true;
    }
    else
    {
        return false;
    }
}

FString UUDPNetworkingWrapper::GrabWaitingMessage()
{
    uint32 Size;

    TSharedRef<FInternetAddr> Sender = SocketSubsystem->CreateInternetAddr();

    while (SenderSocket->HasPendingData(Size))
    {
        int32 Read = 0;
        uint8 element = 0;
        ReceivedData.Init(element, FMath::Min(Size, 65507u));
        SenderSocket->RecvFrom(ReceivedData.GetData(), ReceivedData.Num(), Read, *Sender);
    }


    return StringFromBinaryArray(ReceivedData);

}

bool UUDPNetworkingWrapper::anyMessages()
{

    uint32 Size;

    if (SenderSocket->HasPendingData(Size))
    {
        return true;
    }

    return false;
}

FString UUDPNetworkingWrapper::StringFromBinaryArray(const TArray<uint8>& BinaryArray)
{
    //Create a string from a byte array!
    const std::string cstr(reinterpret_cast<const char*>(BinaryArray.GetData()), BinaryArray.Num());

    //FString can take in the c_str() of a std::string
    return FString(cstr.c_str());

}

void UUDPNetworkingWrapper::UDPDestructor()
{
    SocketSubsystem->DestroySocket(SenderSocket);
    SenderSocket = nullptr;
    SocketSubsystem = nullptr;
    //myRecieverWorker = nullptr;
}



May I ask you how you switched to TCP from this code? Is it simple?

I tested many plugins for Hololens 2 with udp and tcp communication, only this working in emulator, thanks… maybee others help too and save some time like my :slight_smile:
If you have problem to recieve message must enable bounds checkbox, then working…

for TCP communication i found
https://www.programmersought.com/article/91094430036/

If someone want full duplex UDP communication in hololens 2 emulator and external python application some test is published there:
http://193.87.95.129/openvision2/index.php/en/

Hi, I’m a green hand about ue4. I don’t know how to use CPP class UDPNetworkingWrapper in UE4. Could you please give me example about this? Thanks a lot.

This literally is an example. Can you be more specific as to your question?

some comments about the entire topic: For the stated purpose in the original post, I’d think about considering TCP rather than UDP. TCP would make a lot more sense for the stated purposes. Unreal uses UDP networking because you frequently don’t care if you lose some packets here and there when you’re replicating a ton of changing information all the time (among other reasons) but for things like getting user information, updating servers with information, whatever, you probably want those communications to be reliable.

Also, Python isn’t often chosen as a socket server sort of language, a curious implementation choice, I’m curious what the author’s reasoning for choosing Python was.