将字符串,整数和浮点数序列化为字符数组,以便在没有库的情况下进行联网

wsd*_*wsd 9 c++ serialization

我想通过网络传输数据,但我不想使用任何外部库(标准C/C++没问题).

例如:

unsigned int x = 123;
char y[3] = {'h', 'i', '\0'};
float z = 1.23f;
Run Code Online (Sandbox Code Playgroud)

我想要这个

char xyz[11];
Run Code Online (Sandbox Code Playgroud)

阵列.

注意:要通过网络传输它,我需要unsigned int(htonl函数)的网络字节顺序,然后我需要以某种方式将float序列化为IEEE 754格式(互联网上的许多功能),我知道.

如何让它们进入xyz-Array,端到端排列好,所以我可以用它作为socket + send()函数的缓冲区?显然我有反向功能(ntohl和反向IEEE 754)来解决它们,但我也需要一种技术,最好是相同的......

它会是这样的:

xyz in binary: 
00000000 0000000 00000000 01111011 | 01101000 | 01101001 | 00000000 | 00111111 10011101 01110000 10100100
- big endian repr. of u. int 123 - | - 'h'  - | - 'i'  - | - '\0' - | -   IEEE 754 repr of float 1.23   -

如何在没有外部库和最少使用标准库函数的情况下实现此目的?这不是我的计划,而是我的学习.

Car*_*kuk 18

啊,你想序列化原始数据类型!原则上,有两种方法:第一种方法是,您只需获取要序列化的数据的内部二进制表示形式,将其重新解释为一个字符,并在表示时使用它:

所以,如果你有一个:

双d;

你获取它的地址,重新解释该指针作为指向字符的指针,然后使用这些字符:

double *pd=&d;
char *pc = reinterpret_cast<char*>(pd); 
for(size_t i=0; i<sizeof(double); i++) 
{
   char ch = *pc;   
   DoSomethingWith(ch);   
   pc++;
}
Run Code Online (Sandbox Code Playgroud)

这适用于所有原始数据类型.这里的主要问题是,binray表示是依赖于实现的(主要取决于CPU).(当你尝试使用IEEE NANs时,你会遇到微妙的错误...).

总而言之,这种方法根本不可移植,因为您无法控制数据的表示.

第二种方法是,使用更高级别的表示,您自己可以控制.如果性能不是问题,可以使用std :: strstream和>>和<<运算符将原始C类型变量流式传输到std :: strings.这很慢但易于阅读和调试,并且非常便于携带.

  • 有信号 NaN 和非信号 NaN。当您将这些表示形式用作字符数组时,您可以轻松地读取和写入它们。但是,当您将它们作为浮点数访问时,仅读取它们的行为就会导致 CPU 发出信号。因此,如果您不小心,您最终可能会得到一个反序列化没有问题的程序,但是一旦您触及浮动,您就会遇到麻烦。由于这个帖子是关于学习的,我想我可以指出这个领域。 (2认同)
  • 性能总是一个问题:)这仍然是这篇文章中最清晰的答案,谢谢! (2认同)

Jer*_*ner 8

类似下面的代码会做到这一点.注意sizeof(unsigned int)在不同系统上的不同问题,这些问题会得到你.对于这样的事情,你最好使用定义明确的类型,比如int32_t.无论如何...

unsigned int x = 123;
char y[3] = {'h', 'i', '\0'};
float z = 1.23f;

// The buffer we will be writing bytes into
unsigned char outBuf[sizeof(x)+sizeof(y)+sizeof(z)];

// A pointer we will advance whenever we write data
unsigned char * p = outBuf;

// Serialize "x" into outBuf
unsigned int32_t neX = htonl(x);
memcpy(p, &neX, sizeof(neX));
p += sizeof(neX);

// Serialize "y" into outBuf
memcpy(p, y, sizeof(y));
p += sizeof(y);

// Serialize "z" into outBuf
int32_t neZ = htonl(*(reinterpret_cast<int32_t *>(&z)));
memcpy(p, &neZ, sizeof(neZ));
p += sizeof(neZ);

int resultCode = send(mySocket, outBuf, p-outBuf, 0);
[...]
Run Code Online (Sandbox Code Playgroud)

...当然接收代码会做类似的事情,除了反过来.