HI ,
It’s not mandatory use 2 computers for debugging, you can test with your own, by connecting sockets with self connection 127.0.0.1
I made that example some time ago, I connect my little toy car with arduino and my cel phone and yeah!!, I use UDP sockets.
take a look:
I create a simple class inheriting from UActorComponent with few methods inside, I share you:
my header:
#pragma once
#include "Networking.h"
#include "Engine.h"
#include "SocketPower.Generated.h"
USTRUCT(BlueprintType)
struct FAnyCustomData
{
GENERATED_USTRUCT_BODY()
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "DATA")
float motor = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "DATA")
float servo = 0;
FAnyCustomData()
{}
};
FORCEINLINE FArchive& operator<<(FArchive &Ar, FAnyCustomData& TheStruct)
{
Ar << TheStruct.motor;
Ar << TheStruct.servo;
return Ar;
}
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FGetReceivedData, const FAnyCustomData&, receivedData);
UCLASS(meta = (BlueprintSpawnableComponent), ClassGroup = (Hardware))
class USocketPower : public UActorComponent
{
GENERATED_BODY()
private:
bool isServer = false;
FSocket* socket;
FUdpSocketReceiver* UDPReceiver = nullptr;
FAnyCustomData dataRev;
public:
TSharedPtr<FInternetAddr> RemoteAddr;
UPROPERTY(BlueprintAssignable)
FGetReceivedData OnSuccess;
UFUNCTION(BlueprintPure, Category = "Internet")
FAnyCustomData getDataRev();
UFUNCTION(BlueprintCallable, Category = "Internet")
bool sendData(FAnyCustomData data);
UFUNCTION(BlueprintCallable, Category = "Internet")
bool tryToConnect(FString socketname, FString IP, int32 port, bool UDP = false);
UFUNCTION(BlueprintCallable, Category = "Internet")
bool startServer(FString socketname, FString IP, int32 port);
UFUNCTION(BlueprintCallable, Category = "Internet")
void closeConnection();
void Recv(const FArrayReaderPtr& ArrayReaderPtr, const FIPv4Endpoint& EndPt);
};
my cpp:
#include "SocketFuncPrivatePCH.h"
#include "SocketPower.h"
bool USocketPower::startServer(FString socketname, FString IP, int32 port)
{
FIPv4Address Addr;
FIPv4Address::Parse(IP, Addr);
//Create Socket
FIPv4Endpoint Endpoint(Addr, port);
//BUFFER SIZE
int32 BufferSize = 2 * 1024 * 1024;
socket = FUdpSocketBuilder(*socketname)
.AsNonBlocking()
.AsReusable()
.BoundToEndpoint(Endpoint)
.WithReceiveBufferSize(BufferSize);
;
FTimespan ThreadWaitTime = FTimespan::FromMilliseconds(100);
UDPReceiver = new FUdpSocketReceiver(socket, ThreadWaitTime, TEXT("UDP RECEIVER"));
UDPReceiver->OnDataReceived().BindUObject(this, &USocketPower::Recv);
if (socket)
{
isServer = true;
}
return isServer;
}
bool USocketPower::tryToConnect(FString socketname, FString IP, int32 port, bool UDP)
{
RemoteAddr = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateInternetAddr();
bool bIsValid;
RemoteAddr->SetIp(*IP, bIsValid);
RemoteAddr->SetPort(port);
if (!bIsValid)
{
GEngine->AddOnScreenDebugMessage(-1,3,FColor::Red,"IP address was not valid!");
return false;
}
socket = FUdpSocketBuilder(*socketname).AsReusable().WithBroadcast();
//Set Send Buffer Size
int32 SendSize = 2 * 1024 * 1024;
socket->SetSendBufferSize(SendSize, SendSize);
socket->SetReceiveBufferSize(SendSize, SendSize);
if (socket)
{
return true;
}
return false;
}
bool USocketPower::sendData(FAnyCustomData data)
{
if (!socket || isServer)
{
GEngine->AddOnScreenDebugMessage(-1, 3, FColor::Red, "no sender socket");
return false;
}
FArrayWriter Writer;
Writer << data;
int32 BytesSent = 0;
socket->SendTo(Writer.GetData(), Writer.Num(), BytesSent, *RemoteAddr);
if (BytesSent <= 0)
{
GEngine->AddOnScreenDebugMessage(-1, 3, FColor::Red, "invalid send");
return false;
}
return true;
}
void USocketPower::closeConnection()
{
if (UDPReceiver)
{
delete UDPReceiver;
UDPReceiver = nullptr;
}
if (socket)
{
socket->Close();
ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->DestroySocket(socket);
}
}
void USocketPower::Recv(const FArrayReaderPtr& ArrayReaderPtr, const FIPv4Endpoint& EndPt)
{
FAnyCustomData Data;
*ArrayReaderPtr << Data;
FAnyCustomData copy;
copy.motor = Data.motor;
copy.servo = Data.servo;
dataRev = copy;
}
FAnyCustomData USocketPower::getDataRev()
{
return dataRev;
}
It’s super simple, I think is enough clear, but if you have some troubles, let me know
Cheers!