Hello!
For now I am working on a project where I need to have communications between programs on another PC’s by TCP/IP.
My idea how to do this was:
- Create a socket.
- Set his connection parameters (address and port).
- Activate a timer which starts function which check whether the connection with the server is possible.
- Send simple message for now.
The problem is, as I mentioned in the topic is with TSharedRedd<FInsternetAddr>. I want to pass it to the function which is in the timer.
Below are my .cpp and .h codes.
.cpp
#include "TCP.h"
// Sets default values
ATCP::ATCP()
{
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
}
// Called when the game starts or when spawned
void ATCP::BeginPlay()
{
Super::BeginPlay();
LaunchTCP();
}
// Called every frame
void ATCP::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
LaunchTCP();
}
bool ATCP::LaunchTCP() {
UE_LOG(LogTemp, Warning, TEXT("TCP -> Starting..."));
ConnectionSocket = CreateConnectionSocket();
if (!ConnectionSocket) {
UE_LOG(LogTemp, Error, TEXT("Cannot create socket."));
return false;
}
FIPv4Address address;
FIPv4Address::Parse(IP, address);
TSharedRef<FInternetAddr> addr = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateInternetAddr();
addr->SetIp(address.Value);
addr->SetPort(Port);
ConnectionDelegate.BindUFunction(this, FName("CheckConnection"), addr);
GetWorldTimerManager().SetTimer(ConnectionTimerHandle, ConnectionDelegate, 1.f, false);
return true;
}
FSocket * ATCP::CreateConnectionSocket()
{
FSocket* ConnectSock = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateSocket(NAME_Stream, TEXT("TCP"), false);
return ConnectSock;
}
bool ATCP::CheckConnection(const TSharedRef<FInternetAddr>& addr)
{
if (ConnectionSocket->Connect(*addr)) {
UE_LOG(LogTemp, Warning, TEXT("Connection done."));
GetWorldTimerManager().SetTimer(SendMessTimerHandle, this, &ATCP::SendMessage, 2.f, false);
return true;
}
else {
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("Waiting for the server...")));
return false;
}
}
void ATCP::SendMessage()
{
FString serialized = "I am the message from UE4.";
TCHAR* serializedChar = serialized.GetCharArray().GetData();
int32 size = FCString::Strlen(serializedChar);
int32 sent = 0;
bool successful = ConnectionSocket->Send((uint8*)TCHAR_TO_UTF8(serializedChar), size, sent);
if (successful) {
UE_LOG(LogTemp, Warning, TEXT("Message Sent."));
}
return;
}
.h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Runtime/Networking/Public/Interfaces/IPv4/IPv4Address.h"
#include "Runtime/Sockets/Public/Sockets.h"
#include "Runtime/Engine/Public/TimerManager.h"
#include "Runtime/Sockets/Public/SocketSubsystem.h"
#include "Runtime/Core/Public/Templates/SharedPointer.h"
#include "Runtime/Sockets/Public/IPAddress.h"
#include "Runtime/Engine/Classes/Engine/Engine.h"
#include "TCP.generated.h"
UCLASS()
class TCPSTEPBYSTEP_API ATCP : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
ATCP();
UPROPERTY(EditAnywhere)
FString IP = "127.0.0.1";
UPROPERTY(EditAnywhere)
int32 Port = 8890;
FSocket* ConnectionSocket;
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
bool LaunchTCP();
FSocket* CreateConnectionSocket();
bool CheckConnection(const TSharedRef<FInternetAddr>& addr);
void SendMessage();
private:
FTimerDelegate ConnectionDelegate;
FTimerHandle ConnectionTimerHandle;
FTimerHandle SendMessTimerHandle;
};
Now program compiled successfully. But when played it crashes. In the crash log I can see problem with the ConnectionDelegate in the LauchTCP() method.
I tried to type UFUNCTION() before the bool CheckConnection(const TSharedRef& addr) but I can’t compile it. The error is →
Unrecognized type tsharedref - type must be UCLASS, USTRUCT or UENUM
Thanks in advance