简体   繁体   English

网络协议的字节序

[英]Endianness in network protocol

I would like your advise please. 我想请你指教。 I need to implement some protocol using tcp client/server. 我需要使用tcp客户端/服务器实现一些协议。 It has several messeges, some of the with odd number of bytes such as: 它有多个消息,其中一些具有奇数个字节,例如:

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

What do you think is the best way to implement it, in order to avoid byte ordering issues. 您认为什么是实现它的最佳方法,以避免字节顺序问题。 I thought of the following principles: 我想到了以下原则:

  1. use pragma pack(1) on struct defintions to avoid padding 在结构定义上使用pragma pack(1)以避免填充
  2. use htons/htonl when read/write from/into struct for example: 在对结构进行读/写操作时,请使用htons / htonl,例如:

    mymsg1.opcode = htons(0x1234); mymsg1.opcode = htons(0x1234);

    mymsg1.value = 0x56; mymsg1.value = 0x56;

Some of the messeges are more ugly such as the following which it's number of bytes is unknown before run-time, and I still not sure what the best way to define it for sending. 有些消息比较丑陋,例如以下消息,它的字节数在运行时之前是未知的,我仍然不确定定义发送它的最佳方法是什么。

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

Thanks, Ran 谢谢,冉

My inclination would be to avoid "overlay casts" as a means of reading structured data. 我的倾向是避免“覆盖转换”作为读取结构化数据的一种方式。 If performance isn't critical, it may be helpful to define methods like: 如果性能不是很关键,则定义以下方法可能会有所帮助:

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

Given an array uint8_t dat[6] and a structure consisting of an 8-bit value, a 16-bit little-endian value, and a 32-bit big-value in that order, one would then write: 给定一个数组uint8_t dat[6]和一个依次包含8位值,16位小端值和32位大值的结构,则可以这样写:

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

The above code will be portable independent of byte order. 上面的代码是可移植的,与字节顺序无关。 It would be nicer if the function calls and pointer arithmetic could be eliminated, but eliminating those would require either explicitly specifying the offset of each field in the data structure, or else using some really icky macros to do so. 如果可以消除函数调用和指针算术,那就更好了,但是要消除这些函数,则需要显式地指定数据结构中每个字段的偏移量,或者使用一些非常棘手的宏来实现。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM