网络协议中的字节序

时间:2014-07-01 20:36:06

标签: networking struct tcpclient endianness pragma

我想请你的建议。 我需要使用tcp客户端/服务器实现一些协议。它有几个消息,其中一些具有奇数个字节,例如:

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

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

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

    mymsg1.opcode = htons(0x1234);

    mymsg1.value = 0x56;

  3. 有些messeges更难看,例如下面的字节数在运行时之前是未知的,我仍然不确定将其定义为发送的最佳方式。

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

    谢谢,Ran

1 个答案:

答案 0 :(得分:0)

我倾向于避免"叠加演员"作为阅读结构化数据的一种手段。如果性能不重要,那么定义以下方法可能会有所帮助:

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);

上述代码将是可移植的,与字节顺序无关。如果可以消除函数调用和指针运算会更好,但是消除这些将需要显式指定数据结构中每个字段的偏移量,或者使用一些非常icky的宏来执行此操作。