说是详解,实在是有愧。只不过是自己前段时间不理解,花费了点时间来总结下而已。因此此篇文章完全代表自己主观的观点^_^
关于"大小字节序"方面的知识详见BLOG前一篇文章<<大字节序 小字节序>>
那么,先理清下在网络传输里这个字节序转换的过程。假设是一台小字节序的PC机,构造好包后,以大字节(即网络流)方式传输,接着达到终端。我一开始以为传输的时候把高低字节替换,其实不是,只是一个读取值的顺序不同而已。本着这个,来看看IP头格式的定义:
标准的IP头的第一个字节里,是先版本,后首部长度,后来在很多代码里看到这两个是相反的。当时就很纳闷。比如这个定义
那么就从主机-网络-主机这个流程走一遍;
这是我们在主机上构造的一个字节数据:
首部长度:4 版本:4
高地址 低地址
经过网络时,大字节的读取是从低到高,刚好符合,如果我们这样按规范构造
版本:4 首部长度:4
高地址 低地址
经过网络时,大字节的读取是从低到高,刚好是相反的
而在API辅助方面只有atohs atohl两种16位和32位的转换,对8位的无能为力。当然也可以自己构造一个
那么再举个例子,IP字段第二个字节的后16位是
3位标志位 13位偏移
u_int16_t ip_off;
假设我要把第二位标志的BIT设为1,那么可以直接这样
ip_off = 0x40
可以这样来理解,假设这是主机中二进制的排列
0010 0000 0000 0000
高 低
那么在网络传输时,网络层是这样读的,从低位的右三位为标志符,剩下都是偏移,那么实际上我们要设置的是
0000 0000 0100 0000
即0x40
关于"大小字节序"方面的知识详见BLOG前一篇文章<<大字节序 小字节序>>
那么,先理清下在网络传输里这个字节序转换的过程。假设是一台小字节序的PC机,构造好包后,以大字节(即网络流)方式传输,接着达到终端。我一开始以为传输的时候把高低字节替换,其实不是,只是一个读取值的顺序不同而已。本着这个,来看看IP头格式的定义:
标准的IP头的第一个字节里,是先版本,后首部长度,后来在很多代码里看到这两个是相反的。当时就很纳闷。比如这个定义
#if defined(WORDS_BIGENDIAN)
u_int8_t ip_version: 4,
/* 版本 */
ip_header_length: 4;
/* 首部长度 */
#else
u_int8_t ip_header_length: 4,
/* 首部长度 */
ip_version: 4;
/* 版本 */
#endif
那么就从主机-网络-主机这个流程走一遍;
这是我们在主机上构造的一个字节数据:
首部长度:4 版本:4
高地址 低地址
经过网络时,大字节的读取是从低到高,刚好符合,如果我们这样按规范构造
版本:4 首部长度:4
高地址 低地址
经过网络时,大字节的读取是从低到高,刚好是相反的
而在API辅助方面只有atohs atohl两种16位和32位的转换,对8位的无能为力。当然也可以自己构造一个
那么再举个例子,IP字段第二个字节的后16位是
3位标志位 13位偏移
u_int16_t ip_off;
假设我要把第二位标志的BIT设为1,那么可以直接这样
ip_off = 0x40
可以这样来理解,假设这是主机中二进制的排列
0010 0000 0000 0000
高 低
那么在网络传输时,网络层是这样读的,从低位的右三位为标志符,剩下都是偏移,那么实际上我们要设置的是
0000 0000 0100 0000
即0x40