使用C实现与体系结构无关的数字序列化/反序列化

使用C实现与体系结构无关的数字序列化/反序列化,c,serialization,deserialization,cross-platform,C,Serialization,Deserialization,Cross Platform,我正在开发用C编写的小型客户机-服务器应用程序 要将无符号32位数字发送到远程端,请使用以下代码: u_int32_t number = 123; send(client_socket_, &number, 4, CLIENT_SOCKET_FLAGS); u_int32_t number; recv(acceptor, &number, 4, SERVER_DATA_SOCKET_FLAGS); printf("Number is: %u\n", number); 要在远程

我正在开发用C编写的小型客户机-服务器应用程序

要将无符号32位数字发送到远程端,请使用以下代码:

u_int32_t number = 123;
send(client_socket_, &number, 4, CLIENT_SOCKET_FLAGS);
u_int32_t number;
recv(acceptor, &number, 4, SERVER_DATA_SOCKET_FLAGS);
printf("Number is: %u\n", number);
要在远程端接收此号码,请使用此代码:

u_int32_t number = 123;
send(client_socket_, &number, 4, CLIENT_SOCKET_FLAGS);
u_int32_t number;
recv(acceptor, &number, 4, SERVER_DATA_SOCKET_FLAGS);
printf("Number is: %u\n", number);
如果客户机和服务器运行在相同的处理器amd64体系结构上,则一切正常。 但是,如果我的客户端应用程序在不同的处理器架构上启动,mips-I在服务器上获取的字节数无效,则顺序颠倒

如何在体系结构上独立地以二进制格式序列化我的数字

一个重要特性是二进制序列化器/反序列化器的良好性能。 此外,解决方案不应绑定到库。

序列化

static void Ser_uint32_t(uint8_t arr [sizeof(uint32_t)], uint32_t value)
{
    arr[0] = (value >> 24u) & 0xFFu;
    arr[1] = (value >> 16u) & 0xFFu;
    arr[2] = (value >>  8u) & 0xFFu;
    arr[3] = (value >>  0u) & 0xFFu;
}
static uint32_t DeSer_uint32_t(const uint8_t arr [sizeof(uint32_t)])
{
    uint32_t x = 0;
    x |= (uint32_t)(arr[0]) << 24u;
    x |= (uint32_t)(arr[1]) << 16u;
    x |= (uint32_t)(arr[2]) <<  8u;
    x |= (uint32_t)(arr[3]) <<  0u;

    return x;
}
和反序列化

static void Ser_uint32_t(uint8_t arr [sizeof(uint32_t)], uint32_t value)
{
    arr[0] = (value >> 24u) & 0xFFu;
    arr[1] = (value >> 16u) & 0xFFu;
    arr[2] = (value >>  8u) & 0xFFu;
    arr[3] = (value >>  0u) & 0xFFu;
}
static uint32_t DeSer_uint32_t(const uint8_t arr [sizeof(uint32_t)])
{
    uint32_t x = 0;
    x |= (uint32_t)(arr[0]) << 24u;
    x |= (uint32_t)(arr[1]) << 16u;
    x |= (uint32_t)(arr[2]) <<  8u;
    x |= (uint32_t)(arr[3]) <<  0u;

    return x;
}

根据需要的尾数,您可以更正发布的函数

我更喜欢使用十六进制编码。 DEADBEEF的字面意思是:DEADBEEF

这种方法的优点是不会失去使用的能力。 这种方法的缺点是每个数字字节都要加倍

转换很容易,可以在屏蔽半字节后使用查找表。
这有点像使用json之类的东西,但执行起来更轻量级。

因为我看到了socket、server和client这几个词,为什么不使用and?@PeterT,tnx。这也很好用!您必须将数字转换为网络协议的endianess。这才是最重要的。它可能与发送方和/或接收方CPU的endianess相同,也可能不同。次要挑剔:您应该声明const unsigned char**p,因为反序列化时不会修改数组。次要挑剔:更好的选择可能是使用数组语法。静态uint32_t DeSer_uint32_t const uint8_t arr[sizeofuint32_t]因为这使代码更具可读性:x |=uint32_tarr[0]@Lundin是的,正如您所建议的,它更具可读性。关于增量:是的,可以避免传递4个字节和返回对传递的缓冲区的越界访问。这种方法还有一个更显著的缺点,即数据有时会作为EFBEADED发送。。。有CPU端,也有网络协议端。@Lundin,不是snprintf。此外,字节流不应被平台端号更改。如果endian在那里很重要的话,它将是一个基于块的接口。你的答案中没有snprintf。无论如何,转换为ASCII可能不是最好的主意,因为它会带来额外的开销。