UE依据TCP协议传递数据的实现方式

UE依据TCP协议传递数据的实现方式

TCP协议是一种基于字节流的传输层通信协议,在UE中传输字节流可以通过原生C++或者UE c++两种方式。

c++ 中的字节流

C++的主要数据类型,主要分为三类:布尔型,整型(char型从本质上说,也是种整型类型,它是长度为1的整数,通常用来存放字符的ASCII码),浮点型。而 *_t是typedef定义的表示标志,是结构的一种标注。即我们所看到的 uint8_t、uint16_t、uint32_t都不是新的数据类型,而是通过typedef给类型起得别名。*uint8_t是用1个字节表示的;uint16_t是用2个字节表示的;uint32_t是用4个字节表示的。

typedef signed char             int8_t;
typedef short int               int16_t;
typedef int                     int32_t;

typedef unsigned char           uint8_t;
typedef unsigned short int      uint16_t;
typedef unsigned int            uint32_t;
uint8_t  num=67; 

cout << num << endl;		//输出结果为C

C++ 中将uint8_t 作为字节流的基本单位,其基本转化如下:

// 基础类型到容器转换
template <typename T>
std::vector<std::uint8_t> ToByte(T input)
{
	std::uint8_t* bytePointer = reinterpret_cast<std::uint8_t*>(&input);
	return std::vector<std::uint8_t>(bytePointer, bytePointer + sizeof(T));
}

// 容器到基础类型转换
template <typename T>
std::vector<std::uint8_t>& operator>>(std::vector<std::uint8_t>& in, T& out)
{
	if (in.size() >= sizeof(T)) {
		out = *reinterpret_cast<T*>(in.data());
		in.erase(in.begin(), in.begin() + sizeof(T));
	}else {
		out = T{ 0 };
	}
	return in;
}

UEC++ 中的字节流

UE中的基础数据数字类型

bool:代表布尔值 (永远不要假设布尔值的大小) BOOL 将不会进行编译
TCHAR:代表字符型(永远不要假设TCHAR的大小)

uint8:代表无符号字节(占1个字节)
int8:代表有符号的字节(占1个字节)
uint16:代表无符号"短整型" (占2 个字节)
int16:代表有符号"短整型" (占2 个字节)
uint32:代表无符号整型(占4字节)
int32:代表带符号整型(占4字节)
uint64:代表无符号"四字" (8个字节)
int64:代表有符号"四字"(8个字节)

float:代表单精度浮点型 (占4 个字节)
double:代表双精度浮点型 (占8 个字节)
PTRINT:代表可以存放一个指针的整型 (永远不要假设PTRINT的大小)

虚幻引擎(UE)中的所有字符串都作为FStringsTCHAR数组以[UTF-16](http://en.wikipedia.org/wiki/UTF-16/UCS-2)格式存储在内存中。大多数代码假设2个字节等于一个代码点。UEC++ 中的基本字节 用 uint8存储。

UE中的字符转换

对于确定内存大小的 类型如 int、float、FVector2D 等可以直接用memcpy(写入地址, 准备写入数据的起始地址, 写入的数据大小)` 的方式 直接操作内存读写。

而对于FString、FText等类型,就可以考虑先统一成转化成TCHAR数组,再将数组中的单个CHAR直接转化成uint8后组合成uint8组,进行传递。

由于要传递中文字符,当读取/转化时要用到 TCHAR_TO_UTF8UTF8_TO_TCHAR这两个方法。

ByteArrary实现

////LByteArrary.h

class LByteArrary
{

public:
	template<typename T>
	T ReadBytes();

	template<typename T>
	void WriteBytes(T u);

	void WriteString(FString message);
	FString ReadString(int size);

	int32 ByteAvaliable();   //计算剩余字节数
	void Memcpy(void const* _Src, size_t _Size);   // _Src :原字符地址 , _Size:要拷贝的字节大小


public:
	LByteArrary(int32 size);
	~LByteArrary();
public:
	TArray<uint8> Datas;
	int32 ActLength;   // 本次操作的实际长度
	int32 Position;   //	  本次操作的具体位置

};


template<typename T>
inline T LByteArrary::ReadBytes() {

	T res = 0;
	int n = sizeof(T);
	if (ActLength - Position < n) return res;
    
	memcpy(&res, Datas.GetData() + Position, n);
	Position += n;
	return res;

}

template<typename T>
inline void LByteArrary::WriteBytes(T u) {

	int n = sizeof(T);
	// 若Data数组不够写,则对Data手动扩容
	if (Datas.Num()<n)
	{
		Datas.AddUninitialized(n);
	}
	memcpy(Datas.GetData() + Position, &u, n);
	Position += n;
	ActLength = Position;
	return ;
}

//LByteArrary.cpp

#include "LByteArrary.h"

void LByteArrary::WriteString(FString message)
{
	TCHAR* seriallizedChar = message.GetCharArray().GetData();
	int32 size = FCString::Strlen(seriallizedChar);
	size += 4;     // 服务器要求预留一个结束位(int 4字节)
	if (Datas.Num()-Position<size) //Datas.Num()-Position  数组还剩多少长度
	{
		Datas.AddUninitialized(size);
	}
	memcpy(Datas.GetData() + Position, (uint8*)TCHAR_TO_UTF8(seriallizedChar), size - 4);
	Position += size;
	ActLength = Position;

}

FString LByteArrary::ReadString(int size)
{

	uint32 StringLength = ReadBytes<uint32>();
	const FString ReceivedString = FString(StringLength, UTF8_TO_TCHAR(Datas.GetData() + Position));
	Position += StringLength;
	return ReceivedString;


​	
}


int32 LByteArrary::ByteAvaliable()
{
	return ActLength - Position;
}

void LByteArrary::Memcpy(void const* _Src, size_t _Size)
{
	if (Datas.Num()-Position< _Size)
	{
		Datas.AddUninitialized(_Size);
	}

	memcpy(Datas.GetData() + Position, _Src, _Size);
	Position += _Size;
	ActLength = Position;

}

LByteArrary::LByteArrary(int32 size)
{
	Datas.Init(0, size);
}

LByteArrary::~LByteArrary()
{
}

代码参考自 https://www.bilibili.com/video/BV1Xk4y1B7Q4?p=17&vd_source=ecf09c4e73dd9afbbf64e026474a25e0

作者 : [天空游荡的鱼](https://space.bilibili.com/453151910)

posted @ 2023-02-11 15:27  __冫冫  阅读(243)  评论(0编辑  收藏  举报