局域网通信
通过之前的学习,我们了解了应用层,传输层,网络层的协议和作用,这里先做个总结
- 应用层——http,https协议,也可以自己定义一套,作用是进行数据的处理
- 传输层——tcp,udp协议。保证数据传输的可靠性,提供了一个可靠的能力
- 网络层——ip协议。解决了a主机如何在错综复杂的网络世界中找到b主机,发送的报文可能丢失,但是上层tcp提供可靠性,所以tcp/ip协议可以实现a,b主机之间可靠地互发信息
a主机到b主机之间,必然是经过多次的一层一层的局域网转发的,局域网内是如何转发的,这就是数据链路层要解决的事情
局域网通信就如石头丢进湖里激起的波纹,一个主机要向另一台主机发送消息,就要向局域网里所有的主机都发送信息,主机收到后解析ip是否是自己的,是的话就继续向上解析,不是则丢弃
这里就要用到mac协议了,mac地址是48位的,14亿x2^16,足够大,可以实现全球唯一,不像ip地址一样不够使用
ip协议+路由器+nat只解决了确定目标主机的问题,具体一个局域网里是怎么传送的呢?
a主机要在一个局域网里发送给b主机,此时a拿着自己的ip报文,里面有目标主机的ip,但是不知道b的mac地址,只有知道了才能在mac协议中填写b的mac地址,然后向一个局域网内所有主机发送,b收到后解析发现是传给自己的,就继续解包分用了
mac
mac协议=目的mac(6字节)+源mac(6字节)+帧类型(2字节)+有效载荷+CRC(碰撞检测)
mac的有效载荷可以分为三种:ip报文,arp请求/arp应答,rarp请求/rarp应答,通过帧类型判断
- 0800为ip报文
- 0806位arp请求/应答
- 8035位rarp请求/应答
如何将报头和有效载荷进行分离?固定长度
有效载荷如何向上交付?两字节帧类型,判断是交给数据链路层上层的arp还是网络层ip
上面场景中,我们说了a要在局域网中要和b通信,必须要先知道b的mac地址,此时需要arp
arp是处于数据链路层上层一点的,mac是数据链路层下层一点的,所以arp是夹在ip和mac之间的
假设我们通过arp获得了b的mac地址(发起arp请求的时候目的mac填为全f,表示广播)
此时a,b进行通信的时候,就会将帧类型填位0800,表示有效载荷为ip报文,向局域网里每个主机发送,b收到后先取出报头,发现目的ip是macb,且有效载荷为ip报文,此时就会向上交付给ip层处理,不会交给arp了。
这大概就是mac的传输流程,下面我们再来了解一下arp协议
arp
arp夹在网络层和数据链路层之间
下面借用了一下龙哥的文章,自己写出来总感觉不通顺
原文链接:https://blog.csdn.net/chenlong_cxy/article/details/124788397
arp请求,广播报文
arp应答
arp发送请求
arp报文的请求字段
- 硬件类型指链路层的网络类型,1为以太网。
- 协议类型指要转换的地址类型,0x0800为IP地址。
- 硬件地址长度对于以太网地址为6字节,因为MAC地址是48位的。
- 协议地址长度对于IP地址为4字节,因为IP地址是32位的。
- op字段为1表示ARP请求,op字段为2表示ARP应答。
前四个请求和应答填的都是一样的,根据第五个来区分是arp请求还是arp应答
arp的完整流程(路由器D向B主机发送信息)
根据ip与子网掩码确认和B的网络号一致,在同一局域网中,准备获得B的mac地址,进行通信
路由器D构建arp请求,向同一局域网里的所有主机发送
首先,因为路由器a构建的是ARP请求,因此ARP请求当中的op字段设置为1。
- ARP请求当中的硬件类型字段设置为1,因为当前使用的是以太网通信。
- ARP请求当中的协议类型设置为0800,因为路由器是要根据主机B的IP地址来获取主机B的MAC地址。
- ARP请求当中的硬件地址长度和协议地址长度分别设置为6和4,因为MAC地址的长度是48位,IP地址的长度是32位。
- ARP请求当中的发送端以太网地址和发送端IP地址,对应就是路由器D的MAC地址和IP地址。
- ARP请求当中的目的以太网地址和目的IP地址,对应就是主机B的MAC地址和IP地址,但由于路由器D不知道主机B的MAC地址,因此将目的以太网地址的二进制序列设置为全1,表示在局域网中进行广播
ARP请求构建完成后,为了能将ARP请求发送到以太网当中,还需要将ARP数据包向下交付给MAC帧协议,封装成MAC帧
- 封装MAC帧报头时,以太网目的地址和以太网源地址,对应分别是主机B和路由器D的MAC地址,但由于路由器D不知道主机B的MAC地址,因此MAC帧报头当中的以太网目的地址的二进制序列也只能设置为全1,表示在局域网中进行广播。
- 因为这里封装的是一个ARP请求数据包,因此MAC帧当中的帧类型字段设置为0806。
- 由于ARP请求数据包的长度只有28字节,不足46字节,因此还需要在MAC帧的有效载荷当中补上18字节的填充字段,最后再对MAC帧进行CRC校验即可。
- 此时该局域网中的所有主机都收到该mac帧,发现目的ip为全f,且帧类型为0806,为arp请求或应答,则交给arp
- 当ARP层收到这个数据包后,发现ARP数据包当中的op字段为1,于是判定这是一个ARP请求,然后再提取出ARP数据包当中的目的IP地址字段,虽然局域网当中的所有主机都会将该数据包交给自己的ARP层,但最终只有主机B发现ARP数据包当中的目的IP地址与自己相同,因此只有主机B会对该ARP请求进行应答,而局域网当中的其他主机在识别到ARP数据包当中的目的IP地址与自己不匹配后,就会直接将这个ARP请求报文丢弃。
需要注意的是,局域网当中其他不相干的主机在收到这个ARP请求报文后,不是在MAC帧层丢弃的,而是在ARP层发现该ARP数据包的目的IP与自己的IP不匹配后丢弃的。
总结:
发起方构建ARP请求,以广播的方式发送给每一个主机。
每台主机都能识别接收,然后根据MAC帧的帧类型字段将有效载荷交付给每个主机的ARP层。
其他不相关主机立马根据目的IP,在自己的ARP协议内部丢弃ARP请求,只有目标主机会处理请求
arp发送应答
主机B在应答时首先需要构建ARP应答。
- 首先,因为主机B构建的是ARP应答,因此ARP协议当中的op字段设置为2。
- ARP应答当中的硬件类型、协议类型、硬件地址长度、协议地址长度的值与ARP请求当中设置的值相同。
- ARP应答当中的发送端以太网地址和发送端IP地址,对应就是主机B的MAC地址和IP地址。
- ARP应答当中的目的以太网地址和目的IP地址,对应就是路由器D的MAC地址和IP地址,因为路由
此时ARP请求就被封装成MAC帧了,如下:
- 此时局域网当中的每台主机在底层都能收到这个MAC帧,但局域网当中的不相干的主机,在发现该MAC帧对应的以太网目的地址与自己不同后,就会将该MAC帧丢弃,而不会交付给上层ARP层,最终只有路由器D会将解包后MAC帧的有效载荷向上交付给自己的ARP层。
- 当路由器D的ARP层收到这个数据包后,发现ARP数据包当中的op字段为2,于是判定这是一个ARP应答,然后就会提取出ARP数据包当中的发送端以太网的地址和发送端IP地址,此时路由器D就拿到了主机B的MAC地址。
至此,路由器D知道了B的mac地址,就可以进行局域网通信了
arp缓存表
如果每次通信前都要进行arp请求应答那也太麻烦,所以在第一次arp请求的时候,会将对应的信息进行保存一段时间,第二次发送信息就可以直接发送了
结论:
- 主机得到arp应答,会将arp应答缓存起来(有时间限制),如果收到许多同类型的,会将最新的缓存起来
- 任何一台主机,都可能即会收到arp应答,又会收到arp请求
碰撞问题
因为局域网中任何一个主机要发消息,所有主机都要收到,如果这个时候又有另一台一起发,就会产生碰撞
所以局域网中,任何时候只允许一台主机发送数据,如果同时发送会产生数据碰撞的问题
mac帧最后的crc用来检测是否发生碰撞,如果发生则执行碰撞避免算法,简单理解就是发生碰撞的主机等待一段时间后再发
数据分片
tcp中我们讲到将缓冲区理解成一个一个的环形字节数组,是因为数据链路层的原因
受限于物理底层各种因素,如果要传送的数据太大,是会分片的,也就是将一个大的数据分成几个小的数据来发送
ip协议第二行字段就是用来分片用的
上面根据mac帧报文我们知道,MAC帧携带的有效载荷的最大长度是有限制的,也就是说IP交给MAC帧的报文不能超过某个值,这个值就叫做最大传输单元(Maximum Transmission Unit,MTU),这个值的大小一般是1500字节。
由于MAC帧无法发送大于1500字节的数据,因此IP层向下交付的数据的长度不能超过1500字节,这里所说的数据包括IP的报头和IP的有效载荷
如果IP层要传送的数据超过了1500字节,那么就需要先在IP层对该数据进行分片,然后再将分片后的数据交给下层MAC帧进行发送
如果发送数据时在IP层进行了分片,那么当这些分片数据到达对端主机的IP层后就需要先进行组装,然后再将组装好的数据交付给上层传输层。
分片一定是不好的,提高了数据的发送个数,增加了丢包概率
如何做到不分片呢?将每次发送的数据限制在规定大小内,这也是之前为什么tcp发送缓冲区画成一小格一小格的原因
分片和组装都是在ip层完成的,传输层和数据链路层不需要关心
- 传输层只负责为数据传送提供可靠性保证,比如当数据传送失败后,传输层的TCP协议可以组织进行数据重传。
- 当TCP将待发送的数据交给IP后,TCP并不关心该数据是否会在IP层进行分片,即TCP并不关心数据具体的发送过程。
- 当TCP从IP获取到数据后,TCP也不关心该数据是否在IP层经过了组装。
而链路层的MAC帧只负责,将数据从一个节点传送到和自己相连的下一个节点。
- 当IP将待发送的数据交给MAC帧后,MAC帧并不知道该数据是IP经过分片后的某个分片数据,还是一个没有经过分片的数据,MAC帧只知道它一次最多只能发送MTU大小的数据,如果IP交给MAC帧大于MTU字节的数据,那MAC帧就无法进行发送。
- 当MAC帧从网络中获取到数据后,MAC帧也不关心这个数据是否需要进行组装,MAC帧只需要将该数据的MAC帧报头去掉后直接上交给上层IP就行了,而至于该数据的组装问题则是IP需要解决的。
因此,数据的分片和组装完全是由IP协议自己完成的,传输层和链路层不必关心也不需要关心。
分片的过程
ip的第二行字段
- 16位标识:唯一标识主机发送的报文,如果数据在IP层进行了分片,那么每一个分片报文的16位标识是相同的。
- 3位标志:第一位保留,表示暂时没有规定该字段的意义。第二位表示禁止分片,表示如果报文长度超过MTU,IP模块就会丢弃该报文。第三位表示“更多分片”,如果报文没有进行分片,则该字段设置为0,如果报文进行了分片,则除了最后一个分片报文设置为0以外,其余分片报文均设置为1。
- 13位片偏移:分片相对于原始数据开始处的偏移,表示当前分片在原数据中的偏移位置,实际偏移的字节数是这个值× 8 \times 8×8得到的。因此除了最后一个报文之外,其他报文的长度必须是8的整数倍,否则报文就不连续了
假设IP层要发送4500字节的数据,由于超过MTU,IP需要先将该数据进行分片,然后再将一个个的分片交给MAC帧进行发送
分片报文 | 总字节数 | IP报头字节数 | 数据字节数 | 16位标识 | “更多分片” | 13位片偏移 |
---|---|---|---|---|---|---|
1 | 1500 | 20 | 1480 | 123 | 1 | 0 |
2 | 1500 | 20 | 1480 | 123 | 1 | 185 |
3 | 1500 | 20 | 1480 | 123 | 1 | 370 |
4 | 80 | 20 | 60 | 123 | 0 | 555 |
分片的组装
MAC帧交给iP层的数据可能来自世界各地,这些数据可能是经过分片后发送的,也可能是没有经过分片直接发送的,因此IP必须要通过某种方式来区分收到的各个数据。
- IP报头当中有32位源IP地址,源IP地址记录了发送端所对应的IP地址,因此通过IP报头当中的32位源IP地址就可以区分来自不同主机的数据。
- IP报头当中有16位标识,未分片的数据各自的16位标识都是不同的,而由同一个数据分片得到的各个分片报文所对应的16位标识都是相同的,因此通过IP报头当中16位标识就可以判断哪些报文是没有经过分片的独立报文,哪些报文是经过分片后的分片报文。
- 因此IP可以通过IP报头当中的32位源IP地址和16位标识,将经过分片的数据各自聚合在一起,聚合在一起后就可以开始进行组装了。
对于各个分片报文来说:
- 第一个分片报文中的13位片偏移的值一定为0。
- 最后一个分片报文中的“更多分片”标志位一定为0。
- 对于每一个分片报文来说,当前报文的13位片偏移加上当前报文的数据字节数 ÷ \div÷ 8所得到的值,就是下一个分片报文的所对应的13位片偏移。
- 根据分片报文的这三个特点就能够将分片报文合理的组装起来。
先找到分片报文中13位片偏移为0的分片报文,然后提取出其IP报头当中的16位总长度字段,通过计算即可得出下一个分片报文所对应的13位片偏移,按照此方式依次将各个分片报文拼接起来。
直到拼接到一个“更多分片”标志位为0的分片报文,此时表明分片报文组装完毕。
分片报文丢包的问题
片后的报文在网络传输过程中也可能会出现丢包问题,但接收端有能力判断是否收到了全部分片报文,比如假设某组分片报文对应的16位标识值为x:
- 如果分片报文中的第一个分片报文丢包了,那么接收端收到的分片报文中就找不到对应16位标识为x,并且13位片偏移为0的分片报文。
- 如果分片报文中的最后一个分片报文丢包了,那么接收端收到的分片报文中就找不到对应16为标识为x,并且“更多分片”标志位为0的分片报文。
- 如果分片报文中的其它分片报文丢包了,那么接收端在进行分片报文的组装时就会找不到对应13位片偏移为特定值的分片报文。
- 需要注意的是,未分片报文的“更多分片”标志位为0,最后一个分片报文的“更多分片”标志位也为0,但当接收端只收到分片报文中的最后一个分片报文时,接收端不会将其识别成一个未分片的报文,因为未分片的报文所对应的13位片偏移的值也应该是0,而最后一个分片报文所对应的13位片偏移的值不为0。
因此只有当一个报文的13位片偏移为0,并且该报文的“更多分片”标志位也为0时,该报文才会被识别成一个没有被分片的独立报文,否则该报文就会被识别成一个分片报文。