缘起
解包的时候发现数据包里面多了一层mpls,有时会有两层,一层是4字节,如果是多层,每一层里面会有一位,指示当前这层是不是mpls栈的最底层,那就好办了,与(&)一下获得这个位的信息就好了嘛,然后脑袋就短路了,出现了疑问三连
- 我该咋与(&)呢?
- 这个位是在这个字节的哪个位置呢?
- 看着不是在头就是在尾,
& 0x80
还是& 0x01
呢?
上面这些问题还真是让我懵逼了一下下,让我意识到,可能需要去了解一下网络数据传输中的位域问题。这个问题其实之前就遇到过,想必也已经去了解过,这次遇到居然又卡住了,真是不应该啊,这次就记录一下吧
研习
在之前对大小端的学习中的两个东西估计你早忘了,那就是MSB(most significant bit,最高有效位)
和LSB(least significant bit,最低有效位)
,一个字节,从bit0到bit7,对于大端来说,bit0是MSB,bit7是LSB,对于小端来说,bit7是MSB,bit0是LSB
ip首部的第一个字节包含了ip版本
信息和ip首部长度
信息,所以这里也涉及到了位域,那么就以此为例
|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Version| IHL |Type of Service| Total Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
这是ip首部的一部分,根据RFC791 Page 38的描述,每个字节的最左边,即,标记为0的,是最高有效位,传输时,也是先传输最高有效位,就以最常见的情况,ip版本为4,ip首部长度为20字节,那么对应到首部结构,就应该是这个样子
MSB | LSB | ||||||
---|---|---|---|---|---|---|---|
bit0 | bit1 | bit2 | bit3 | bit4 | bit5 | bit6 | bit7 |
0 | 1 | 0 | 0 | 0 | 1 | 0 | 1 |
既然先传输的是MSB,那计算机先接收的肯定也是MSB嘛,肯定也要存储在本地的MSB上,所以,小端的计算机接收下来存储后就是这样的格式
MSB | LSB | ||||||
---|---|---|---|---|---|---|---|
bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 |
0 | 1 | 0 | 0 | 0 | 1 | 0 | 1 |
用十六进制表示那就是0x45
,所以说ip版本其实是在高4位,而ip首部长度则是在低4位,这也对应了头文件中ip的结构体里面,如果是小端,则长度信息在前,版本信息在后
#if __BYTE_ORDER == __LITTLE_ENDIAN
unsigned int ip_hl:4; /* header length */
unsigned int ip_v:4; /* version */
#endif
#if __BYTE_ORDER == __BIG_ENDIAN
unsigned int ip_v:4; /* version */
unsigned int ip_hl:4; /* header length */
#endif
结论
定位到那个字节之后,& 0x01