Hi! I’m new to this community and c++ programming.
I follow Ramas TCP Socket tutorial. And I’ve got some errors that I don’t know how to solve it.
// Fill out your copyright notice in the Description page of Project Settings.
#include "tcpip.h"
#include <String>
#include "tcpiptest.h"
#include "Engine.h"
#include "Runtime/Engine/Public/TimerManager.h"
void tcpiptest::tcpiptest()
{
//IP = 127.0.0.1, Port = 8890 for my Python test case
if (!StartTCPReceiver("RamaSocketListener", "127.0.0.1", 8890))
{
//UE_LOG "TCP Socket Listener Created!"
return;
}
//UE_LOG "TCP Socket Listener Created! Yay!"
}
bool tcpiptest::StartTCPReceiver(
const FString& YourChosenSocketName,
const FString& TheIP,
const int32 ThePort
) {
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,
&tcpiptest::TCPConnectionListener, 0.01, true);
return true;
}
bool tcpiptest::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[i] = FCString::Atoi(*Parts[i]);
}
return true;
}
FSocket* tcpiptest::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;
}
void tcpiptest::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);
//UE_LOG "Accepted Connection! WOOOHOOOO!!!";
//can thread this too
GetWorldTimerManager().SetTimer(this,
&tcpiptest::TCPSocketListener, 0.01, true);
}
}
}
FString tcpiptest::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());
}
void tcpiptest::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()));
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Rama'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));
}
tcpiptest::~tcpiptest()
{
}
Where is the exact same code I’ve copy from Rama’s tutorial page.
The error I’ve recieved.
- Failed to produce item: C:\Unreal4.13 Projects\tcpip\Binaries\Win64\UE4Editor-tcpip.pdb
- MSB3075 ““C:\Program Files (x86)\Epic Games\4.13\Engine\Build\BatchFiles\Build.bat” tcpipEditor Win64 Development “C:\Unreal4.13 Projects\tcpip\tcpip.uproject” -waitmutex” exited with code 5. Please verify that you have sufficient rights to run this command.
- ‘tcpiptest::tcpiptest()’ :constructors not allowed a return type
- left of ‘.SetTimer’ must have class/struct/union
- Undefined GetWorldTimerManager(), VShow
- cannot convert parameter 1 from ‘TArray *’ to ‘TArray &’
- Error code C2660
I put the code in my newly c++ class ‘tcpiptest.cpp’
I don’t really know the fact that if I’m doing the right thing.
Can anyone please help me?
Thanks a lot!
p.s I’m using ue4.13.1