IP报头 version 和 ihl 大小端异位

from GavinJun
IP报头结构
IP报头 version 和 ihl 大小端异位_第1张图片

C语言结构体

struct iphdr  
  {  
#if __BYTE_ORDER == __LITTLE_ENDIAN  
    unsigned int ihl:4;     //首部的长度  
    unsigned int version:4;     //协议版本号,4/6 ,表示IPV4/IPV6  
#elif __BYTE_ORDER == __BIG_ENDIAN  
    unsigned int version:4;  
    unsigned int ihl:4;  
#endif  
    u_int8_t tos;       //Type Of Service 服务类型字段  
    u_int16_t tot_len;  //IP数据包的总长度  
    u_int16_t id;       //标识字段  
    u_int16_t frag_off;     //Fragment Offset 分段偏移,   
    u_int8_t ttl;       //Time To Live 最大为255,每经过一个路由减去1  
    u_int8_t protocol;  //协议,比如TCP是6,UDP是8,ICMP是1,在in.h中有定义  
    u_int16_t check;    //首部校验和  
    u_int32_t saddr;    //源IP地址  
    u_int32_t daddr;    //目的IP地址  
    /*The options start here. */  
  };  

按理来说 version 应该放在 ihl 前面,可是为什么在大、小端模式下顺序不同?

可以这样来解释

1)从道理上来说,little endian 中的位应该这样排列:
01234567
即排在前面的是低位。因此,先分配 least significant bits
2)而在 big endian 中,位应该这样排列:
76543210
即排在前面的是高位。因此,先分配 most significant bits。

可以这样来理解

1)在 big endian 的情况下,"排在前面的是高位"

a. 对于顺序的两个字节来说,第一个字节是高位(排在前面),第二个字节是低位(排在后面)。

b. 对于字节内部的位来说,
-------most significant bits排在前面,是高位,
-------least significant bits排在后面,是低位。
2)在 little endian 的情况下,"排在前面的是低位"

a. 对于顺序的两个字节来说,第一个字节是低位(排在前面),第二个字节是高位(排在后面)。

b. 对于字节内部的位来说,
-------least significant bits排在前面,是低位,
-------most significant bits排在后面,是高位。

这样,在对struct中的成员进行分配的时候,"按排列顺序分配,先分配排在前面的"

1)big endian从高位向低位分配,

a. 对字节,是先分配低地址的字节,再分配高地址的字节。

b. 对位域,先分配most significant bits,再分配least significant bits。
1)little endian从低位向高位分配,

a. 对字节,是先分配低地址的字节,再分配高地址的字节。

b. 对位域,先分配least significant bits,再分配most significant bits。

以上说的都是分配的顺序

对于IP协议来说
1)IP's byte order is big endian.
2)The bit endianness of IP inherits that of the CPU,
3)and the NIC takes care of converting it from/to the bit transmission/reception order on the wire.

并且,按照IP协议
1)"version" is the most significant four bits of the first byte of an IP header.
2)"ihl" is the least significant four bits of the first byte of the IP header.

也就是说,version 必须分配在 most significant four bits,
按照上面说的分配顺序,在big endian中,version 必须放在前面

#include <stdio.h> 
int main() 
{ 
    char* c; 
    struct bitfield { 
        int ia:3; 
        int ib:2; 
        int ic:3; 
    } field; 

    field.ia=4; 
    field.ib=2; 
    field.ic=2; 

    c=(char *) &field; 
    printf("%d ",*c); 
    return 0; 
}  

在对struct中的成员进行分配的时候,"按排列顺序分配,先分配排在前面的"

struct 排列成 100 10 010

a)little endian从低位向高位分配,
b)对位域,先分配least significant bits,再分配most significant bits。

按照字面上理解,分配后成 010 01 001 (76543210) 实际上是 010 10 100

所以:先分配 least significant 3 bits,再分配middle 2 bits,最后分配most significant 3 bits。

就像这样:

1)"version" is the most significant 4 bits of the first byte of an IP header.
2)"ihl" is the least significant 4 bits of the first byte of the IP header.

所谓的“对位域,先分配least significant bits,再分配most significant bits”
并不是说分配是bit by bit的,而是根据结构的定义,以结构成员为单位,一组一组地,依次分配到位组。

ia=100排在最前面,因此作为一组,分配到least significant 3 bits,
ib=10排在中间,因此作为一组,分配到接下来的middle 2 bits,
ic=010排在最后面,因此作为一组,分配到most significant 3 bits。

你可能感兴趣的:(IP报头 version 和 ihl 大小端异位)