假设我们有一个二进制协议(protocol),其中的字段按网络顺序排列(大端)。
struct msg1
{
int32 a;
int16 b;
uint32 c
}
如果不是将网络缓冲区复制到我的 msg1,然后使用“networkToHost”函数读取 msg1
我将 msg1 重新排列/反转为
struct msg1
{
uint32 c
int16 b;
int32 a;
}
然后简单地从网络缓冲区做一个反向复制来创建 msg1。在这种情况下,不需要 networkToHost 函数。这种惯用的方法在大端机器上不起作用,但对我来说这不是问题。除此之外,还有其他我想念的缺点吗?
谢谢
附言对于以上内容,我们强制执行严格对齐(#pragma pack(1)
等)
最佳答案
除此之外,还有其他我想念的缺点吗?
恐怕您误解了端序转换问题的本质。 “Big endian”并不意味着您的字段是反向排列的,因此
struct msg1_bigendian
{
int32 a;
int16 b;
uint32 c
}
在大端架构上相当于一个
struct msg1_littleendian
{
uint32 c;
int16 b;
int32 a;
}
关于小端架构。相反,它意味着每个字段中的字节顺序 是相反的。让我们假设:
a = 0x1000000a;
b = 0xb;
c = 0xc;
在大端架构上,这将被布局为:
10 00 00 0a
00 0b
00 00 00 0c
高阶(最重要的)字节在前。
在小端机器上,这将被布局为:
0a 00 00 10
0b 00
0c 00 00 00
最低位在前,最高位在后。
序列化它们并将消息的序列化形式叠加在一起,您会发现不兼容:
10 00 00 0a 00 0b 00 00 00 0c (big endian)
0a 00 00 10 0b 00 0c 00 00 00 (little endian)
int32 a int16 b int32 c
请注意,这不仅仅是字段反向运行的情况。你的提议会导致小端机器将大端表示误认为是:
a = 0xc000000; b = 0xb00; c = 0xa000010;
当然不是传输的内容!
对于传输的每个字段,您确实必须将每个单独的字段转换为网络字节顺序,然后再转换回来。
更新:
好的,我明白你现在想做什么了。您想要反向定义结构,然后从字节字符串的 end 到开头进行 memcpy(反向复制)并以这种方式反转字节顺序。在这种情况下,我会说,是的,这是一个 hack,是的,它使您的代码不可移植,是的,这是不值得的。事实上,字节顺序之间的转换并不是一个非常昂贵的操作,而且它比反转每个结构的布局更容易处理。
关于c++ - 二进制协议(protocol) - 字节交换技巧,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/646842/