unreal engine c++ 创建tcp server, tcp client

这篇具有很好参考价值的文章主要介绍了unreal engine c++ 创建tcp server, tcp client。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

TCP客户端

TcpConnect.h

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "Common/UdpSocketReceiver.h"
#include "GameFramework/Actor.h"

DECLARE_DELEGATE_TwoParams(FOnServerResponseReceived, const int32&, bool);

class FTcpConnect : public FRunnable
{
public:
	// Sets default values for this actor's properties
	FTcpConnect();

	virtual ~FTcpConnect()
	{
		if (ReceiveThread != nullptr)
		{
			ReceiveThread->Kill(true);
			delete ReceiveThread;
		}
	}
	// virtual FSingleThreadRunnable* GetSingleThreadInterface() override
	// {
	// 	return this;
	// }
public:
	// Called every frame

	void ConnectToServer(FString ServerAddress, const int32 ServerPort);
	void SendMessage(const FString& Message);

	FOnServerResponseReceived& OnDataReceived()
	{
		return OnServerResponseReceived;
	}

	virtual bool Init() override;
	virtual void Stop() override;

protected:


	virtual uint32 Run() override;

	virtual void Exit() override;


private:
	FSocket* Socket;
	TSharedPtr<FInternetAddr> RemoteAddr;
	FIPv4Endpoint LocalEndpoint;
	TArray<uint8> ReceivedData;
	FUdpSocketReceiver* UDPReceiver;
	bool bIsReceiving;
	FRunnableThread* ReceiveThread;
	int64 StartMs;

	FOnServerResponseReceived OnServerResponseReceived;
};

TcpConnect.cpp

// Fill out your copyright notice in the Description page of Project Settings.


#include "Subsystem/TcpConnect.h"

// Sets default values
FTcpConnect::FTcpConnect()
{
}


void FTcpConnect::ConnectToServer(FString ServerAddress, const int32 ServerPort)
{
	// 
	Socket = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateSocket(NAME_Stream, TEXT("default"), false);

	// 
	RemoteAddr = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateInternetAddr();
	bool bValid;
	RemoteAddr->SetIp(*ServerAddress, bValid);
	RemoteAddr->SetPort(ServerPort);
	if (Socket->Connect(*RemoteAddr))
	{
		UE_LOG(LogTemp, Display, TEXT("Connected to server"));

		// 
		bIsReceiving = true;
		ReceiveThread = FRunnableThread::Create(this, TEXT("ReceiveThread"), 128 * 1024);
	}
	else
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to connect to server"));
	}
}

void FTcpConnect::SendMessage(const FString& Message)
{
	if (Socket)
	{
		const TCHAR* MessageData = *Message;
		int32 BytesSent = 0;
		StartMs = FDateTime::Now().ToUnixTimestamp() * 1000.0 + FDateTime::Now().GetMillisecond();
		UE_LOG(LogTemp, Warning, TEXT(" start ms %d"), StartMs);
		Socket->Send((uint8*)TCHAR_TO_UTF8(MessageData), FCString::Strlen(MessageData), BytesSent);
	}
}

// FOnServerResponseReceived& FTcpConnect::OnDataReceived()
//
// {
// 	// check(ReceiveThread == nullptr);
// 	return OnServerResponseReceived;
// }


bool FTcpConnect::Init()
{
	if (ReceiveThread && Socket)
	{
		return true;
	}
	return false;
}

void FTcpConnect::Stop()
{
	bIsReceiving = false;

	if (ReceiveThread)
	{
		ReceiveThread->WaitForCompletion();
		// ReceiveThread.re
	}

	if (Socket)
	{
		Socket->Close();
		Socket = nullptr;
		// Socket.Reset();
	}
}

uint32 FTcpConnect::Run()
{
	while (bIsReceiving)
	{
		uint8 Data[1024];
		int32 BytesReceived = 0;
		if (Socket->Recv(Data, sizeof(Data), BytesReceived, ESocketReceiveFlags::None))
		{
			if (BytesReceived > 0)
			{
				FString Message = FString(UTF8_TO_TCHAR((const char*)Data));
				UE_LOG(LogTemp, Warning, TEXT(" message %s"), *Message)

				int64 EndMs = FDateTime::Now().ToUnixTimestamp() * 1000.0 + FDateTime::Now().GetMillisecond();
				UE_LOG(LogTemp, Warning, TEXT(" start ms %d  %d"), EndMs, EndMs- StartMs);
				auto r = OnServerResponseReceived.ExecuteIfBound(EndMs - StartMs, true);
				bIsReceiving = false;
			}
		}
		FPlatformProcess::Sleep(0.05f);
	}

	return 0;
}

void FTcpConnect::Exit()
{
	// FRunnable::Exit();
}

tcp server

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "HAL/Runnable.h"

class FSocket;
class FInternetAddr;

/**
 * 
 */
class MYPROJECT2_API FTcpServer : public FRunnable
{
public:
	FTcpServer();
	~FTcpServer();
	
	// 初始化服务器
	virtual bool Init() override;

	// 开始监听连接
	bool StartListening(FString IpAddress, int32 Port);

	// 停止监听连接
	void StopListening();

	// FRunnable 接口
	virtual uint32 Run() override;
	virtual void Stop() override;
	void HandleTextMessage(const FString& Message);

private:
	// 处理客户端连接
	void HandleConnection(FSocket* NewClientSocket, const TSharedRef<FInternetAddr>& ClientAddress);
	FString StringFromBinaryArray(const TArray<uint8>& BinaryArray);

	class FSocket* serverSocket;
	FSocket* ListenSocket;
	FRunnableThread* ServerThread;
	FThreadSafeBool bIsStopping;

	TMap<FSocket*, FString> ClientDataMap; // 用于存储每个客户端的数据

};

cpp

// Fill out your copyright notice in the Description page of Project Settings.


#include "Net/TcpServer.h"

#include "Common/TcpSocketBuilder.h"
#include "Interfaces/IPv4/IPv4Endpoint.h"

FTcpServer::FTcpServer() : ListenSocket(nullptr), ServerThread(nullptr), bIsStopping(false)
{
	ServerThread = FRunnableThread::Create(this, TEXT("TcpServerThread"));
}

FTcpServer::~FTcpServer()
{
	StopListening();
}


bool FTcpServer::Init()
{
	// 初始化网络模块
	// if (!ISocketSubsystem::Init())
	// {
	// 	UE_LOG(LogTemp, Error, TEXT("Failed to initialize socket subsystem."));
	// 	return false;
	// }

	return true;
}

bool FTcpServer::StartListening(FString IpAddress, int32 Port)
{
	FString ServerIP = IpAddress;
	FIPv4Address ServerAddr;
	if (!FIPv4Address::Parse(ServerIP, ServerAddr))
	{
		UE_LOG(LogTemp, Error, TEXT("Server Ip %s is illegal"), *ServerIP);
	}
	ListenSocket = FTcpSocketBuilder(TEXT("Socket Listener"))
	               .AsReusable()
	               .AsBlocking()
	               .BoundToAddress(ServerAddr)
	               .BoundToPort(Port)
	               .Listening(8)
	               .WithReceiveBufferSize(1024)
	               .WithSendBufferSize(1024);
	if (ListenSocket)
	{
		UE_LOG(LogTemp, Warning, TEXT("Server Create Success!"), *ServerIP);
		// SocketCreateDelegate.Broadcast(true);
		// GetWorld()->GetTimerManager().SetTimer(ConnectCheckHandler, this, &ATCPServer::ConnectCheck, 1, true);
		return false;
	}
	else
	{
		UE_LOG(LogTemp, Error, TEXT("Server Create Failed!"));
		// SocketCreateDelegate.Broadcast(false);
	}
	return false;
}

void FTcpServer::StopListening()
{
	if (ListenSocket)
	{
		ListenSocket->Close();
		ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->DestroySocket(ListenSocket);
		ListenSocket = nullptr;
	}

	if (ServerThread)
	{
		ServerThread->WaitForCompletion();
		delete ServerThread;
		ServerThread = nullptr;
	}
}

uint32 FTcpServer::Run()
{
	ISocketSubsystem* SocketSubsystem = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM);
	if (!SocketSubsystem)
	{
		UE_LOG(LogTemp, Error, TEXT("Socket subsystem not available."));
		return 1;
	}
	
	while (!bIsStopping)
	{
		if (!ListenSocket) continue;

		TSharedRef<FInternetAddr> ClientAddress = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateInternetAddr();
		FSocket* NewClientSocket = ListenSocket->Accept(*ClientAddress, TEXT("MyTcpServer Connection"));
		UE_LOG(LogTemp, Log, TEXT("Run"));

		if (NewClientSocket)
		{
			// 新客户端连接处理
			HandleConnection(NewClientSocket, ClientAddress);
			
		}
		FPlatformProcess::Sleep(0.01);
	}

	return 0;
}

void FTcpServer::Stop()
{
	UE_LOG(LogTemp, Warning, TEXT("St opped"));

	bIsStopping = true;
}

void FTcpServer::HandleTextMessage(const FString& Message)
{
	UE_LOG(LogTemp, Warning, TEXT("Received message: %s"), *Message);
}

void FTcpServer::HandleConnection(FSocket* NewClientSocket, const TSharedRef<FInternetAddr>& ClientAddress)
{
	// 在这里处理新客户端连接的逻辑
	UE_LOG(LogTemp, Warning, TEXT("Client connected: %s"), *ClientAddress->ToString(true));

	// 接收和处理消息
	while (NewClientSocket && !bIsStopping)
	{
		TArray<uint8> ReceivedData;
		uint32 Size;

		// 接收数据
		while (NewClientSocket->HasPendingData(Size))
		{
			ReceivedData.Init(0, FMath::Min(Size, 65507u));
			int32 Read = 0;
			NewClientSocket->Recv(ReceivedData.GetData(), ReceivedData.Num(), Read);

			// 处理接收到的数据(这里假设消息以'\n'分隔)
			FString ReceivedString = StringFromBinaryArray(ReceivedData);
			TArray<FString> Messages;
			ReceivedString.ParseIntoArray(Messages, TEXT("\n"), true);

			for (const FString& Message : Messages)
			{
				// 处理文本消息
				HandleTextMessage(Message);
			}
		}

		// 睡眠一段时间,以避免空循环造成CPU过度使用
		FPlatformProcess::Sleep(0.01);
	}

	// 断开客户端连接
	// UE_LOG(LogTemp, Warning, TEXT("Client disconnected: %s"), *ClientAddress->ToString(true));
	// NewClientSocket->Close();
	// ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->DestroySocket(NewClientSocket);

}

FString FTcpServer::StringFromBinaryArray(const TArray<uint8>& BinaryArray)
{
	return FString(ANSI_TO_TCHAR(reinterpret_cast<const char*>(BinaryArray.GetData())));
}

FTcpServerReceive

h

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "HAL/Runnable.h"

/**
 * 
 */
class MYPROJECT2_API FTcpServerReceive: public FRunnable
{
public:
	FTcpServerReceive(FSocket* InSocket);
	~FTcpServerReceive();
protected:
	virtual bool Init() override;
	virtual void Stop() override;
	FString StringFromBinaryArray(TArray<uint8> Array);
	void HandleTextMessage(const FString& String);
	virtual uint32 Run() override;
private:
	 FSocket* ClientSocket;
	FRunnableThread* ServerReceiveThread;
	bool bIsStopping;
};

cpp

// Fill out your copyright notice in the Description page of Project Settings.


#include "Net/FTcpServerReceive.h"

#include "Sockets.h"
#include "SocketSubsystem.h"


FTcpServerReceive::FTcpServerReceive(FSocket* InSocket)
{
	ClientSocket = InSocket;
	ServerReceiveThread = FRunnableThread::Create(this, TEXT("ServerReceiveThread"));
	bIsStopping = false;
}

FTcpServerReceive::~FTcpServerReceive()
{
	if (ClientSocket)
	{
		ClientSocket->Close();
		ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->DestroySocket(ClientSocket);
		ClientSocket = nullptr;
	}

	if (ServerReceiveThread)
	{
		ServerReceiveThread->WaitForCompletion();
		delete ServerReceiveThread;
		ServerReceiveThread = nullptr;
	}
}

bool FTcpServerReceive::Init()
{
	if (ServerReceiveThread && ClientSocket)
	{
		UE_LOG(LogTemp, Warning, TEXT("  %s start"), *FString(__FUNCTION__));

		return true;
	}
	return false;
}

void FTcpServerReceive::Stop()
{
	bIsStopping = true;
}

FString FTcpServerReceive::StringFromBinaryArray(TArray<uint8> BinaryArray)
{
	return FString(ANSI_TO_TCHAR(reinterpret_cast<const char*>(BinaryArray.GetData())));
}

void FTcpServerReceive::HandleTextMessage(const FString& Message)
{
	UE_LOG(LogTemp, Warning, TEXT("Received message: %s"), *Message);
}

uint32 FTcpServerReceive::Run()
{
	while (ClientSocket)
	{
		TArray<uint8> ReceivedData;
		uint32 Size;

		// 接收数据
		while (ClientSocket->HasPendingData(Size))
		{
			ReceivedData.Init(0, FMath::Min(Size, 65507u));
			int32 Read = 0;
			ClientSocket->Recv(ReceivedData.GetData(), ReceivedData.Num(), Read);

			// 处理接收到的数据(这里假设消息以'\n'分隔)
			FString ReceivedString = StringFromBinaryArray(ReceivedData);
			TArray<FString> Messages;
			ReceivedString.ParseIntoArray(Messages, TEXT("\n"), true);

			for (const FString& Message : Messages)
			{
				// 处理文本消息
				HandleTextMessage(Message);
			}
		}

		// 睡眠一段时间,以避免空循环造成CPU过度使用
		FPlatformProcess::Sleep(0.05);
	}
	return 0;
}

使用

GameInstance 使用文章来源地址https://www.toymoban.com/news/detail-632384.html


void UMyGameInstance::HandleTextMessage(const FString& Message)
{
	UE_LOG(LogTemp, Warning, TEXT("Received message: %s"), *Message);
}

bool UMyGameInstance::Connected(FSocket* Socket, const FIPv4Endpoint& FiPv4Endpoint)
{
	UE_LOG(LogTemp, Warning, TEXT("Connected %s"), *FiPv4Endpoint.ToString());
	FTcpServerReceive* ServerReceive = new FTcpServerReceive(Socket);
	return true;
}


void UMyGameInstance::Init()
{
	Super::Init();


	FIPv4Address ServerAddr;
	FIPv4Address::Parse("0.0.0.0", ServerAddr);

	FIPv4Endpoint IPv4;
	IPv4.Address = ServerAddr;
	IPv4.Port = 6666;

#if UE_SERVER
	/

	FTcpListener* TcpServer = new FTcpListener(IPv4);
	TcpServer->OnConnectionAccepted().BindUObject(this, &UMyGameInstance::Connected);

#else
	FTcpClient* TcpClient = new FTcpClient();
	TcpClient->ConnectToServer("192.168.1.6", 6666);


	FTimerHandle h;
	FTimerDelegate d = FTimerDelegate::CreateLambda([=]()
	{
		FString sent = "aaaaaa";
		TcpClient->SendMessage(sent);
	});

	// GetWorld()->GetTimerManager().SetTimer(h, d, 1.0f, true, 3.0f);

#endif
}

FString UMyGameInstance::StringFromBinaryArray(const TArray<uint8>& BinaryArray)
{
	return FString(ANSI_TO_TCHAR(reinterpret_cast<const char*>(BinaryArray.GetData())));
}

TSharedPtr<TArray<uint8>, ESPMode::ThreadSafe> UMyGameInstance::StringToByteArray(FString DataString)
{
	TArray<uint8> DataArray;
	FTCHARToUTF8 Converter(*DataString);
	DataArray.Append(reinterpret_cast<const uint8*>(Converter.Get()), Converter.Length());
	return MakeShared<TArray<uint8>, ESPMode::ThreadSafe>(MoveTemp(DataArray));
}

到了这里,关于unreal engine c++ 创建tcp server, tcp client的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 游戏编程中的AI与物理模拟——用Unreal Engine创建惊艳的游戏世界

    作者:禅与计算机程序设计艺术 作为游戏开发者,我们经常需要在游戏中加入一些视觉、听觉或者触觉等交互性元素,并且给用户提供更具个性化的游戏体验。游戏制作人员也喜欢利用人工智能(AI)来辅助游戏制作过程,例如制作游戏中的怪物和敌人具有潜在的危险性,能

    2024年02月07日
    浏览(36)
  • python tcp server client示例代码

    功能: 实现基本的tcp server端、client端,并引入threading, 保证两端任意链接、断链接,保证两端的稳定运行 IP说明: server不输入IP,默认为本机的IP,client需要输入要链接的server端的IP 端口说明:server, client端保持一致 ADB调试说明:在连接数据线的情况下,PC安装ADB调试工具,

    2024年02月09日
    浏览(64)
  • TwinCAT3 Modbus-TCP Client/Server使用

    目录 一、环境配置和准备 1、PLC中安装TF6250-Modbus-TCP库 2、勾选TF6250的license 3、PLC工程中添加Tc2_ModbusSrv库文件 4、分别创建测试ModbusTCP测试的Server和Client程序 二、PLC作为Client端 1、设置测试电脑IP地址 2、运行MobusTCP测试工具 3、PLC端程序编写 (1)读取离散量输入 (2)读取线圈

    2024年01月16日
    浏览(33)
  • Android studio TCP网络调试助手应用开发(支持TCP Server与Client切换)

            在前几篇的文章中带大家完成了 基于TCP的物联网安卓应用开发 ,教程内容是创建了一个 TCP客户端并连接服务器完成数据通信的过程 ,后不久又发布了一个 ESP8266创建TCP 服务器与安卓的客户端进行通信 的一个文章,当时在文章中提到“如果大家有需要将ESP8266配置

    2024年02月06日
    浏览(48)
  • 【整活】Unreal Engine 3体验

    今天下了UDK,想在用虚幻5的年头体验一下\\\"上古时代\\\"的虚幻3,链接 安装 跟虚幻4对比,虚幻4可是比它大不少:      一般来说,编辑器程序在这个文件夹中 比如我的这个: 这个UDK.exe就是虚幻3编辑器程序 游戏 双击打开,却发现它默认运行自带的游戏       ......别说这画质还可以..

    2023年04月08日
    浏览(27)
  • Unreal Engine添加UGameInstanceSubsystem子类

    点击C++类文件夹,在右边的区域点击鼠标右键,在弹出的菜单中选择“新建C++类” 在弹出的菜单中选中“显示所有类”,选择GameInstanceSubsystem作为父类, 点击“下一步”按钮 输入子类名称“UVRVIUOnlineGameSubsystem”,选择插件作为新类的目标模块,点击“公共”选择器 打开C++工

    2024年04月26日
    浏览(30)
  • Unreal Engine游戏引擎的优势

    在现在这个繁荣的游戏开发行业中,选择合适的游戏引擎是非常重要的。其中,Unreal Engine作为一款功能强大的游戏引擎,在业界广受赞誉。那Unreal Engine游戏引擎究竟有哪些优势,带大家简单的了解一下。 图形渲染技术 Unreal Engine确实提供了先进的图形渲染技术,包括实时光

    2024年02月03日
    浏览(33)
  • Unreal Engine 与 Blender - 比较指南

    虚幻引擎和 Blender 是游戏开发人员中最常用的两种软件,它们在游戏开发工作流程中都有自己的用途和地位。作为进入视频游戏行业的初学者,可能很难从数十种软件中筛选找到最适合您需求的一款。希望本指南能够缓解这一困难并帮助您决定选择哪个软件。 虚幻引擎是由

    2024年02月16日
    浏览(37)
  • Unreal Engine 游戏中枪的构建

      一、创建枪蓝图 1、创建一个actor蓝图: 在Blueprints文件夹中右键添加蓝图类actor并命名为Gun_BPGun_BP 2、添加骨骼网格体组件 双击打开蓝图类,在左上角组件中添加骨骼网格体组件 3、选择枪模型 选中骨骼网格体组件,将枪的网格体选中为这样 4、将骨骼网格体设置为蓝图的根

    2024年02月03日
    浏览(56)
  • Unreal Engine工程项目目录及对应作用

    目录 .vs Binaries:编译文件 Config:配置文件 Content:资产文件 DerivedDataCache:UE针对平台特化的资源版本 Intermediate:中间文件 Saved:自动保存的内容 Source:源(代码)文件 .sln文件:VS的工程文件 .uproject:虚幻的启动文件 为啥要说这个呢? 有两点: 便于我们管理并查找相应资

    2023年04月19日
    浏览(49)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包