网络传输中的位域

发布时间 2023-05-23 21:52:57作者: start-from-ling

缘起


解包的时候发现数据包里面多了一层mpls,有时会有两层,一层是4字节,如果是多层,每一层里面会有一位,指示当前这层是不是mpls栈的最底层,那就好办了,与(&)一下获得这个位的信息就好了嘛,然后脑袋就短路了,出现了疑问三连

  1. 我该咋与(&)呢?
  2. 这个位是在这个字节的哪个位置呢?
  3. 看着不是在头就是在尾,& 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

参考

关于IP报头定义为什么要区分大小端的原因
Ethernet下字节序和bit序的总结
浅谈大小端(Endian)与位域