Dear Community,
I have just posted my tutorial and entire code for how you can set up a TCP Socket listener to then receive data from an external program!
In my case I was using a simple python script!
The code I am sharing with you in this wiki tutorial is fully functional!
Wiki Tutorial Link
**Picture**
https://www.mediafire.com/convkey/df72/pi10dce0d3y3bs16g.jpg
(open image in new tab to see in better detail)
Entire CPP Code For You
I had to use** std::string** for one very essential part of this process, which was converting the received binary data into a UE4 FString!
**.H**
```
**#include "Networking.h"**
public:
FSocket* ListenerSocket;
FSocket* ConnectionSocket;
FIPv4Endpoint RemoteAddressForConnection;
bool StartTCPReceiver(
const FString& YourChosenSocketName,
const FString& TheIP,
const int32 ThePort
);
FSocket* CreateTCPConnectionListener(
const FString& YourChosenSocketName,
const FString& TheIP,
const int32 ThePort,
const int32 ReceiveBufferSize = 2*1024*1024
);
//Timer functions, could be threads
void TCPConnectionListener(); //can thread this eventually
void TCPSocketListener(); //can thread this eventually
//Format String IP4 to number array
bool FormatIP4ToNumber(const FString& TheIP, uint8 (&Out)[4]);
//'s StringFromBinaryArray
FString StringFromBinaryArray(const TArray<uint8>& BinaryArray);
```
~~~
**.CPP**
```
**#include <string>**
**void AJoyPCEditor::StartsTheWholeProcess!()**
{
if( ! StartTCPReceiver("RamaSocketListener", **"127.0.0.1"**, **8890**))
{
VShow("Could not create the Socket Listener!");
return;
}
}
//'s Start TCP Receiver
**bool AJoyPCEditor::StartTCPReceiver(**
const FString& YourChosenSocketName,
const FString& TheIP,
const int32 ThePort
){
//'s CreateTCPConnectionListener
ListenerSocket = CreateTCPConnectionListener(YourChosenSocketName,TheIP, ThePort);
//Not created?
if(!ListenerSocket)
{
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("StartTCPReceiver>> Listen socket could not be created! ~> %s %d"), *TheIP, ThePort));
return false;
}
//Start the Listener! //thread this eventually
GetWorldTimerManager().SetTimer(this,
&AJoyPCEditor::TCPConnectionListener, 0.01, true);
return true;
}
//Format IP String as Number Parts
**bool AJoyPCEditor::FormatIP4ToNumber(const FString& TheIP, uint8 (&Out)[4])**
{
//IP Formatting
TheIP.Replace( TEXT(" "), TEXT("") );
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// IP 4 Parts
//String Parts
TArray<FString> Parts;
TheIP.ParseIntoArray( &Parts, TEXT("."), true );
if ( Parts.Num() != 4 )
return false;
//String to Number Parts
for ( int32 i = 0; i < 4; ++i )
{
Out* = FCString::Atoi( *Parts* );
}
return true;
}
//'s Create TCP Connection Listener
**FSocket* AJoyPCEditor::CreateTCPConnectionListener(const FString& YourChosenSocketName,const FString& TheIP, const int32 ThePort,const int32 ReceiveBufferSize)
{**
uint8 IP4Nums[4];
if( ! FormatIP4ToNumber(TheIP, IP4Nums))
{
VShow("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;
}
//'s TCP Connection Listener
**void AJoyPCEditor::TCPConnectionListener()
{**
//~~~~~~~~~~~~~
if(!ListenerSocket) return;
//~~~~~~~~~~~~~
//Remote address
TSharedRef<FInternetAddr> RemoteAddress = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateInternetAddr();
bool Pending;
// handle incoming connections
if (ListenerSocket->HasPendingConnection(Pending) && 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("RamaTCP Received Socket Connection"));
if (ConnectionSocket != NULL)
{
//Global cache of current Remote Address
RemoteAddressForConnection = FIPv4Endpoint(RemoteAddress);
VShow("Accepted Connection! WOOOHOOOO!!!");
//can thread this too
GetWorldTimerManager().SetTimer(this,
&AJoyPCEditor::TCPSocketListener, 0.01, true);
}
}
}
**//'s String From Binary Array
//This function requires
// #include <string>**
**FString AJoyPCEditor::StringFromBinaryArray(const TArray<uint8>& BinaryArray)
{**
//Create a string from a byte array!
const std::string cstr( reinterpret_cast<const char*>(BinaryArray.GetData()), BinaryArray.Num() );
return FString(cstr.c_str());
}
//'s TCP Socket Listener
**void AJoyPCEditor::TCPSocketListener()
{**
//~~~~~~~~~~~~~
if(!ConnectionSocket) return;
//~~~~~~~~~~~~~
//Binary Array!
TArray<uint8> ReceivedData;
uint32 Size;
while (ConnectionSocket->HasPendingData(Size))
{
ReceivedData.Init(FMath::Min(Size, 65507u));
int32 Read = 0;
ConnectionSocket->Recv(ReceivedData.GetData(), ReceivedData.Num(), Read);
//GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("Data Read! %d"), ReceivedData.Num()));
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if(ReceivedData.Num() <= 0)
{
//No Data Received
return;
}
VShow("Total Data read!", ReceivedData.Num() );
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("Data Bytes Read ~> %d"), ReceivedData.Num()));
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 's String From Binary Array
const FString ReceivedUE4String = StringFromBinaryArray(ReceivedData);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
VShow("As String!!!!! ~>",ReceivedUE4String);
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("As String Data ~> %s"), *ReceivedUE4String));
}
```
~~~
**The Hardest Part**
The hardest part for me was converting the Python Binary Data received from the TCP socket into a UE4 FString!
Here's the code I wrote to do it!
```
**//'s String From Binary Array
//This function requires
// #include <string>**
FString AJoyPCEditor::****StringFromBinaryArray****(const TArray<uint8>& BinaryArray)
{
//Create a string from a byte array!
const std::string cstr( reinterpret_cast<const char*>(BinaryArray.GetData()), BinaryArray.Num() );
return FString(cstr.c_str());
}
```
~~~
Enjoy!