字节序(byte order)和位序(bit order)
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
字节序(byte order)和位序(bit order)
字节序(byte order)和位序(bit order)
在网络编程中经常会提到网络字节序和主机序,也就是说当一个对象由多个字节组成的时候需要注意对象的多个字节
在内存中的顺序。
以前我也基本只了解过字节序,但是有一天当我看到ip.h中对IP头部结构体struct iphdr的定义时,我发现其中竟然对一个字节中的8个比特位也区分了大小端,这时我就迷糊了,不是说大小端只有在多个字节之间才会有区分的吗,为什么这里的定义却对一个字节中的比特位也区分大小端呢?
下面我们先看一下struct iphdr的定义,后文会解惑为什么要在一个字节中区分大小端。
struct iphdr {
#if defined(__LITTLE_ENDIAN_BITFIELD)
__u8 ihl:4,
version:4;
#elif defined (__BIG_ENDIAN_BITFIELD)
__u8 version:4,
ihl:4;
#else
#error "Please fix "
#endif
__u8 tos;
__be16 tot_len;
__be16 id;
__be16 frag_off;
__u8 ttl;
__u8 protocol;
__sum16 check;
__be32 saddr;
__be32 daddr;
/*The options start here. */
};
字节序(Byte order)
关于字节序的文章已经有很多了,在我这篇文章中不打算过多的说字节序,但是也不能完全脱离字节序因为后面的重点部分比特序跟字节序也有一定的相似度和联系。
字节序就是说一个对象的多个字节在内存中如何排序存放,
比如我们要想往一个地址a中写入一个整形数据
0x12345678,那么最后在内存中是如何存放这四个字节的呢?
0x12这个字节值为最高有效字节,也就是整数值的最高位(在本文中0x12=0x12000000),0x78为最低有效字节。
图1:大端字节序
上图是大端字节序的示意图,所谓”大端字节序”,便是指最高有效字节落在低地址上的字节存放方式。
图2:小端字节序
而小端字节序就是最低有效字节落在低地址上的字节存放方式。
0x12345678=0x12000000 + 0x340000 + 0x5600 + 0x78,所以
要想保持一个对象的值在大小端系统之间不变,那么就必须确保不同的系统能够正确的识别最高有效字节和最低有效
字节(不能错误的识别最高、最低有效字节)。
同样的字节序12 34 56 78在大端序机器中会识别为
0x12345678(0x12000000 + 0x340000 + 0x5600 +
0x78=0x12345678),在小端序机器中识别为0x78563412(0x12 + 0x3400 + 0x5600 00+ 0x78000000=0x78563412)。
所以要想两者保持一致就必须确保系统能够正确的识别最
高有效字节0x12和最低有效字节0x78,那么在小端系统中字节存放的顺序应该为78 56 34 12。
比特序(bit order)
字节序是一个对象中的多个字节之间的顺序问题,比特序就是一个字节中的8个比特位(bit)之间的顺序问题。一般情况下系统的比特序和字节序是保持一致的。
一个字节由8个bit组成,这8个bit也存在如何排序的情况,跟字节序类似的有最高有效比特位、最低有效比特位。
比特序1 0 0 1 0 0 1 0在大端系统中最高有效比特位为1、最
低有效比特位为0,字节的值为0x92。在小端系统中最高、最低有效比特位则相反为0、1,字节的值为0x49。
跟字节序类似,要想保持一个字节值不变那么就要使系统能正确的识别最高、最低有效比特位。
字节序转换函数ntohl(s)、htonl(s)
在socket编程中经常要用到网络字节序转换函数ntohl、htonl 来进行主机序和网络序(大端序)的转换,在主机序为小端的系统中字节序列78 56 34 12(val=0x12345678)经过htonl转换后字节序列变成12 34 56 78:
图3:htonl函数
字节序转换后我在想是不是比特序也一同进行了转换?
为什么会有这个疑问呢,因为前文可知系统的比特序和字节序是一致的,现在字节序已经从小端变成了大端那么比特序应该也要一起转换。而且如果比特序不变化那么当这些字节到了目标大端序系统中后每一个字节的值都会发生变化,因
为同样的比特序列在小端和大端系统中识别的字节值会不一样。
首先从htonl、ntohl的源码来看确实只进行了字节序的转换并没有进行比特序的转换,再有就是以前socket编程的时候只调用了ntohl、htonl等函数并没有调用(而且系统也没有提供)比特序转换函数,但是最后的结果都是正确的,并没有发现上面提到的字节值发生变化的问题。
那么这个”神奇”的事情是怎么解决的呢,好像系统本身就给我们”悄悄”的解决了我担心的问题。
答案我们下文揭晓。
比特(bit)的发送和接收顺序
比特的发送、接收顺序是指一个字节中的bit在网络电缆中是如何发送、接收的。在以太网(Ethernet)中,是从最低有效比特位到最高有效比特位的发送顺序,也就是最低有效比特位首先发送,参考资料:frame。
在以太网中这个规定有点奇怪,因为字节序我们是按照大端序来发送,但是比特序却是按照小端序的方式来发送,下图