Actually I’m able to get it to work, but only on the first launch and connection. If I leave the game running and attempt to connect to the game again, it fails. The client says “Connected”, however it appears the game does not register the problem. I can stop the game in the view port, and restart it, launch the client code. The client will register a connection and that it sent something, however the game will not register anything was received.
EDIT: GOT IT WORKING, putting modified listening code below
Last item I need to figure out is how to send data to a connected client on the socket.
//// Fill out your copyright notice in the Description page of Project Settings.
//
#include “RoboSimStudio.h”
#include “NetworkActor.h”
#include <string>
//
//
//// Sets default values
ANetworkActor::ANetworkActor()
{
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don’t need it.
PrimaryActorTick.bCanEverTick = false;
}
//
//// Called when the game starts or when spawned
void ANetworkActor::BeginPlay()
{
Super::BeginPlay();
//IP = 127.0.0.1, Port = 8890 for my Python test case
if (!StartTCPReceiver(“RamaSocketListener”, “127.0.0.1”, 8423))
{
UE_LOG(LogTemp, Warning, TEXT(“TCP Socket Listener Failed!”));
return;
}
}
//
//// Called every frame
void ANetworkActor::Tick( float DeltaTime )
{
Super::Tick( DeltaTime );
}
//
//Rama’s Start TCP Receiver
bool ANetworkActor::StartTCPReceiver(
const FString& YourChosenSocketName,
const FString& TheIP,
const int32 ThePort
)
{
//Rama’s CreateTCPConnectionListener
ListenerSocket = CreateTCPConnectionListener(YourChosenSocketName, TheIP, ThePort);
//Not created?
if (!ListenerSocket)
{
UE_LOG(LogTemp, Error, TEXT("StartTCPReceiver>> Listen socket could not be created! ~> %s %d"), *TheIP, ThePort);
return false;
}
UE_LOG(LogTemp, Warning, TEXT("StartTCPReceiver>> Listen socket created! ~> %s %d"), *TheIP, ThePort);
//TODO: Start the Listener! //thread this eventually
GetWorldTimerManager().SetTimer(ConnectionListenTimer, this, &ANetworkActor::TCPConnectionListener, 0.01f, true);
return true;
}
//Format IP String as Number Parts
bool ANetworkActor::FormatIP4ToNumber(const FString& TheIP, uint8(&Out)[4])
{
//IP Formatting
TheIP.Replace(TEXT(" “), TEXT(”“));
const TCHAR *delim;
delim = TEXT(”.");
TArray<FString> Parts;
TheIP.ParseIntoArray(Parts, delim, true);
if (Parts.Num() != 4)
return false;
for (int32 i = 0; i < 4; ++i)
{
Out* = FCString::Atoi(*Parts*);
}
return true;
}
//Rama’s Create TCP Connection Listener
FSocket* ANetworkActor::CreateTCPConnectionListener(const FString& YourChosenSocketName, const FString& TheIP, const int32 ThePort, const int32 ReceiveBufferSize)
{
uint8 IP4Nums[4];
if (!FormatIP4ToNumber(TheIP, IP4Nums))
{
UE_LOG(LogTemp, Error, TEXT(“Invalid IP! Expecting 4 parts separated by .”));
return false;
}
//Create Socket
FIPv4Endpoint Endpoint(FIPv4Address(IP4Nums[0], IP4Nums[1], IP4Nums[2], IP4Nums[3]), ThePort);
FSocket* ListenSocket = FTcpSocketBuilder(*YourChosenSocketName)
.AsReusable()
.BoundToEndpoint(Endpoint)
.Listening(8);
//Set Buffer Size
int32 NewSize = 0;
ListenSocket->SetReceiveBufferSize(ReceiveBufferSize, NewSize);
//Done!
return ListenSocket;
}
//Rama’s TCP Connection Listener
void ANetworkActor::TCPConnectionListener()
{
//~~~~~~~~~~~~~
//UE_LOG(LogTemp, Warning, TEXT(“Checking socket…”));
if (!ListenerSocket)
{
UE_LOG(LogTemp, Error, TEXT(“Listener doesn’t exist, but should.”));
return;
}
//Remote address
TSharedRef<FInternetAddr> RemoteAddress = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateInternetAddr();
bool Pending;
// handle incoming connections
if (ListenerSocket->HasPendingConnection(Pending) && Pending)
{
UE_LOG(LogTemp, Warning, TEXT("Connection Pending..."));
//Already have a Connection? destroy previous
if (ConnectionSocket)
{
ConnectionSocket->Close();
ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->DestroySocket(ConnectionSocket);
}
//New Connection receive!
ConnectionSocket = ListenerSocket->Accept(*RemoteAddress, TEXT("TODO: Start Kick off Event"));
if (ConnectionSocket != NULL)
{
//Global cache of current Remote Address
RemoteAddressForConnection = FIPv4Endpoint(RemoteAddress);
//UE_LOG "Accepted Connection! WOOOHOOOO!!!";
UE_LOG(LogTemp, Warning, TEXT("Accepted Connection!"));
//can thread this too
GetWorldTimerManager().SetTimer(SocketListenTimer, this, &ANetworkActor::TCPSocketListener, 0.01f, true);
}
}
}
FString ANetworkActor::StringFromBinaryArray(const TArray<uint8>& BinaryArray)
{
//Create a string from a byte array!
std::string cstr(reinterpret_cast<const char*>(BinaryArray.GetData()), BinaryArray.Num());
return FString(cstr.c_str());
}
//Rama’s TCP Socket Listener
void ANetworkActor::TCPSocketListener()
{
//~~~~~~~~~~~~~
if (!ConnectionSocket) return;
//Binary Array!
TArray<uint8> ReceivedData;
uint32 Size;
while (ConnectionSocket->HasPendingData(Size))
{
ReceivedData.Init(0.0f, FMath::Min(Size, 65507u));
int32 Read = 0;
ConnectionSocket->Recv(ReceivedData.GetData(), ReceivedData.Num(), Read);
UE_LOG(LogTemp, Warning, TEXT("Data Read! %d"), ReceivedData.Num());
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if (ReceivedData.Num() <= 0)
{
//No Data Received
return;
}
const FString ReceivedUE4String = StringFromBinaryArray(ReceivedData);
//Logging
UE_LOG(LogTemp, Warning, TEXT("Total Data read! %d"), ReceivedData.Num());
UE_LOG(LogTemp, Warning, TEXT("As String!!!!! ~> %s"), *ReceivedUE4String);
}