【问题标题】:Endianness in network protocol网络协议中的字节序
【发布时间】:2014-07-01 20:36:05
【问题描述】:

我希望得到您的建议。 我需要使用 tcp 客户端/服务器来实现一些协议。它有几个消息,其中一些带有奇数字节,例如:

typedef struct _msg1
{
unsigned short opcode
unsigned char  value
}msg1;

您认为实现它的最佳方式是什么,以避免字节顺序问题。 我想到了以下原则:

  1. 在结构定义上使用 pragma pack(1) 以避免填充
  2. 在读/写结构时使用 htons/htonl,例如:

    mymsg1.opcode = htons(0x1234);

    mymsg1.value = 0x56;

有些消息更丑陋,例如以下它的字节数在运行时之前是未知的,我仍然不确定定义它以进行发送的最佳方法是什么。

typedef struct _msg_errors
{
unsigned short opcode
unsigned char errortable[DEPENDS_ON_NUMBER_OF_REAL_ERRORS]
}msg_errors;

谢谢,冉

【问题讨论】:

    标签: networking struct tcpclient endianness pragma


    【解决方案1】:

    我倾向于避免将“覆盖转换”作为读取结构化数据的一种方式。如果性能不重要,定义如下方法可能会有所帮助:

    int getBE16(uint8_t **p) { // Big-endian 16-bit
      uint8_t *pp = *p;
      int result = pp[0]*256 + pp[1];
      (*p)+=2;
    }
    int getLE16(uint8_t **p) { // Little-endian 16-bit
      uint8_t *pp = *p;
      int result = pp[0] + 256*pp[1];
      (*p)+=2;
    }
    int getBE32(uint8_t **p) { // Big-endian 32-bit
      uint8_t *pp = *p;
      int result = ((pp[0]*256 + pp[1])*256 + pp[2])*256 + pp[3];
      (*p)+=4;
    }
    int getLE32(uint8_t **p) { // Little-endian 16-bit
      uint8_t *pp = *p;
      int result = pp[0] + 256*(pp[1] + 256*(pp[2] + 256*pp[3]));
      (*p)+=4;
    }
    

    给定一个数组 uint8_t dat[6] 和一个由 8 位值、16 位小端值和 32 位大值依次组成的结构,然后可以这样写:

    uint8_t *p = dat;
    mystruct.theByte = *p++;
    mystruct.theHalfword = getLE16(&p);
    mystruct.theWord = getBE32(&p);
    

    上面的代码可以独立于字节顺序进行移植。如果可以消除函数调用和指针运算会更好,但消除这些需要明确指定数据结构中每个字段的偏移量,或者使用一些非常糟糕的宏来做到这一点。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-07
      • 2021-06-21
      • 2013-12-14
      • 1970-01-01
      • 2012-09-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多