二进制协议 - 字节交换技巧

4 c c++

假设我们有一个二进制协议,字段网络有序(大端).

struct msg1
{
    int32 a;
    int16 b;
    uint32 c
}
Run Code Online (Sandbox Code Playgroud)

而不是将网络缓冲区复制到我的msg1,然后使用"networkToHost"函数来读取msg1

我将msg1重新排列/反向

struct msg1
{
    uint32 c
    int16 b;
    int32 a;
}
Run Code Online (Sandbox Code Playgroud)

并简单地从网络缓冲区执行反向复制以创建msg1.在这种情况下,不需要networkToHost功能.这种习惯用法在大端机器上不起作用,但对我来说这不是问题.除此之外,我还有其他任何缺点吗?

谢谢

PS为上面我们强制严格对齐(#pragma pack(1)等)

cyg*_*gil 20

除此之外,我还有其他任何缺点吗?

我担心你误解了endian转换问题的本质."大端"并不意味着你的领域是反向排列的,所以a

struct msg1_bigendian
{
    int32 a;
    int16 b;
    uint32 c
}
Run Code Online (Sandbox Code Playgroud)

在大端架构上相当于一个

struct msg1_littleendian 
{
   uint32 c;
   int16 b;
   int32 a;
}
Run Code Online (Sandbox Code Playgroud)

在一个小端架构上.相反,它意味着每个字段的字节顺序是相反的.我们假设:

a = 0x1000000a;
b = 0xb;
c = 0xc;
Run Code Online (Sandbox Code Playgroud)

在大端架构上,这将被布置为:

10 00 00 0a
00 0b
00 00 00 0c
Run Code Online (Sandbox Code Playgroud)

首先是高阶(最重要)字节.

在小端机器上,这将被布置为:

0a 00 00 10
0b 00
0c 00 00 00
Run Code Online (Sandbox Code Playgroud)

首先是最低位字节,最后一个是最高位.

序列化它们并将消息的序列化形式叠加在一起,您将发现不兼容性:

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
Run Code Online (Sandbox Code Playgroud)

请注意,这不仅仅是字段反向运行的情况.您的建议会导致一个小端程序机器错误地将大端表示形式误认为:

a = 0xc000000; b = 0xb00; c = 0xa000010;

当然不是传播的东西!

对于传输的每个字段,您确实必须将每个字段转换为网络字节顺序并再次返回.

更新:

好的,我明白你现在要做什么.您希望反向定义结构,然后从字节字符串的末尾到开头(反向复制)的memcpy,并以这种方式反转字节顺序.在这种情况下,我会说,是的,这是一个黑客,是的,它使你的代码不可移植,是的,它是不值得的.事实上,在字节顺序之间进行转换并不是一项非常昂贵的操作,并且它比处理每个结构的布局要容易得多.


rlb*_*ond 6

你确定这是必需的吗?您的网络流量很可能是您的瓶颈,而不是CPU速度.


cod*_*zen 5

同意@ribond -

这对于开发人员来说非常容易混淆,因为他们必须努力将这些与语义相同的结构分开.

鉴于网络延迟比CPU处理它的速度快10,000,000倍,我只是保持它们相同.