[REQUEST] Tutorial to connect to dedicated server (Socket)

Hi,
Would you like to open this topic because it did not find anything even chewed over TCP connection between a game made ​​with the EU4 and dedicated server socket. The server part is very simple because I can create independently of the engine. I’ve been trying a few days a little sketchy tutorials I found but I’m garrando in much the same following the step by step. If anyone has tips or a nice tutorial to post pls send al.
sorry about bad english. :smiley:

I tried to understand this for 3 weeks already :slight_smile:
Here are my topics:

I also very interested in why we can’t compile server without using github source code? We are provided by compiled binaries of UE4 through client distribution app. What is the purpose of it if we can’t compile server from it?

It’s not what he’s asking for

Demonraz: You should look at Rama post here TCP Socket Listener, Receiving Binary Data into UE4 From a Python Script! - C++ - Epic Developer Community Forums
It’s a TCP listener, after that you’ll only need an interface to convert what’s received into something the Engine can understand and a way to communicate back with the server

Alright have followed this tutorial step by step and always end up in error. Below is what I tried to make following this tutorial because maybe someone knows somewhere where I can be wrong and give me a hint how to put Unreal Engine 4.2.0:

1: Create a 3º person project on UE4 and VS2013 open;

2: On VS2013, compile using Win64 and Development Editor(just hit F5). When click to load my project on engine, UE4 ask me to recompile modules because they are out date. I click Yes and my project load!

3: When UE4 Editor load with my project, I back to VS2013 and make changes on source code’s project like below;

MyProject.Build.cs


// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved.

using UnrealBuildTool;

public class MyProject : ModuleRules
{
	public MyProject(TargetInfo Target)
	{
		PublicDependencyModuleNames.AddRange(new string] { "Core", "CoreUObject", "Engine", "InputCore", "Networking", "Sockets" });
	}
}



MyProjectGameMode.h


// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved.
#pragma once

#include "Networking.h"
#include "MyProjectGameMode.generated.h"

UCLASS(minimalapi)
class AMyProjectGameMode : public AGameMode
{
	GENERATED_UCLASS_BODY()
	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]);

	//Rama's StringFromBinaryArray
	FString StringFromBinaryArray(const TArray<uint8>& BinaryArray);
	void StartsTheWholeProcess();
};





MyProjectGameMode.cpp


// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved.

#include "MyProject.h"
#include <string>
#include "MyProjectGameMode.h"

AMyProjectGameMode::AMyProjectGameMode(const class FPostConstructInitializeProperties& PCIP)
	: Super(PCIP)
{
	// set default pawn class to our Blueprinted character
	static ConstructorHelpers::FObjectFinder<UClass> PlayerPawnBPClass(TEXT("Class'/Game/Blueprints/MyCharacter.MyCharacter_C'"));
	if (PlayerPawnBPClass.Object != NULL)
	{
		DefaultPawnClass = PlayerPawnBPClass.Object;

	}
}




void AMyProjectGameMode::StartsTheWholeProcess()
{
	if (!StartTCPReceiver("RamaSocketListener", "127.0.0.1", 8880))
	{

		//VShow("Could not create the Socket Listener!"); //I comment all this because on tutorial don't have this function implemented
		return;
	}
}

//Rama's Start TCP Receiver
bool AMyProjectGameMode::StartTCPReceiver(const FString& YourChosenSocketName, const FString& TheIP, const int32 ThePort)
{
	//Rama'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, &AMyProjectGameMode::TCPConnectionListener, 0.01, true);

	return true;
}

//Format IP String as Number Parts
bool AMyProjectGameMode::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;
}

//Rama's Create TCP Connection Listener
FSocket* AMyProjectGameMode::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;
}


//Rama's TCP Connection Listener
void AMyProjectGameMode::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,
				&AMyProjectGameMode::TCPSocketListener, 0.01, true);
		}
	}
}

//Rama's String From Binary Array
//This function requires 
//		#include <string>
FString AMyProjectGameMode::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());
}

//Rama's TCP Socket Listener
void AMyProjectGameMode::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));
}


4: After all code above, On UE4 Editor I click on “Recompile Game Code” and with some fixes I can complete compile process with successful.

5: When lanch standalone game from editor…i can’t see code changes in action. Even with the server was shutdown in order to see the messages on the screen by the command like


GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("StartTCPReceiver>> Listen socket could not be created! ~> %s %d"), *TheIP, ThePort));

But, I believe c++ functions are not being called because I don’t see entry point like int main() or similar.

Someone help me please.

You need something to call the StartsTheWholeProcess() function. Try adding a call in the constructor. A better solution would be to call it during StartupModule() in MyProject.cpp and clean up in ShutdownModule().

Where I can find StartupModule() and ShutdownModule()? If need to create then, how I can do this? Tks anyway :smiley: