🐱作者:一只大喵咪1201
🐱专栏:《网络》
🔥格言:你只管努力,剩下的交给时间!
来到数据链路层后,完整的数据被叫做数据帧,习惯上称之为MAC帧。
MAC帧协议 | ARP协议
- 🦺以太网协议
- 👑认识MAC地址
- 👑协议报头
- 🦺局域网转发原理
- 👑认识MTU
- 🦺ARP协议
- 👑协议格式
- 👑ARP缓存表
- 🦺回顾整个协议栈
- 🦺总结
🦺以太网协议
网络层的IP协议并不是将数据报直接发到了网络中,而是将数据报继续向下交付,给到了数据链路层。
如上图所示,每一个红色的圈就是一个局域网,假设现在主机A要将数据发送到主机D,这个数据要经过多个局域网,要一跳一跳到达主机D。
- 所以说网络传输的本质,就是多个局域网(子网)转发的结果!!!
数据链路层负责数据在一个局域网中的传送,我们主要研究数据链路层的以太网协议,也被叫做MAC帧协议。
一个局域网中有多台主机,这些主机之间通过以太网等网络连接,进而可以直接通信。
如上图所示便是局域网通信示意图,多台主机处于一个局域网中,通过以太网连接,主机名称从MAC1~MAC7
,其中MAC1
是该局域网的入口路由器,也可以看成是一台主机,因为它也有网卡,具有网络通信的能力。
- “以太网” 不是一种具体的网络,而是一种技术标准,既包含了数据链路层的内容,也包含了一些物理层的内容。
- 以太网规定了网络拓扑结构,访问控制方式,传输速率等,而且网线必须使用双绞线,传输速率有10M, 100M, 1000M等。
- 以太网是当前应用最广泛的局域网技术,和以太网并列的还有令牌环网,无线LAN等。
不管是什么类型的网络,都是用来组成局域网进行网络通信的。
👑认识MAC地址
每台主机都至少有一张网卡,每个网卡都有一个唯一的序列号sn
,这个序列号被叫做MAC地址,该地址全球范围内具有唯一性。
- MAC地址是一个6字节的十六进制序列号,形如
1A:2B:3C:4D:5E:6F
。
我们不是已经有了IP地址了,为什么还要有MAC地址呢?
- IP地址描述的是整个数据传送过程中的起点和终点。
- MAC地址描述的是数据传送过程中,每一跳(一个区间)的起点和终点。
IP地址指引着方向,MAC地址则是投石问路,一步一步来,比如本喵现在要从北京到上海,路途中会经过石家庄,南京,苏州…等地,这个过程中,上海就相当于IP地址,途中经过的城市就相当于MAC地址。
具体在网络中,IP地址就是目标主机,MAC地址就是两个相连路由器,只有一跳一跳经过多个路由器,数据才能被送到目标主机。
- MAC地址严格来说并不需要全球唯一,只需要保证同一个局域网中的唯一性即可。
但是制造厂商在制造的时候将其设置成了全球唯一,主要是因为网卡制造厂商非常多,无法保证不同厂商制造的网卡不会出现在同一个局域网中,所以就直接一刀切了,让MAC地址成为全球唯一。
- 不同厂商可用的MAC地址参照了子网划分的方式,保证不同厂商之间的MAC地址不会重复。
👑协议报头
如上图所示MAC帧协议格式,与之前的TCP/UDP以及IP协议相比,简单了许多,报头只有三个字段:
- 源地址和目的地址是指网卡的硬件地址(MAC地址),长度是48位,是在网卡出厂时固化的,不可以修改。
- 帧协议类型字段有三种值,分别对应IP、ARP、RARP,也就是向上交付时要交付的协议类型。
如上图,0800
表示要分用给IP协议,0806
表示要分用给ARP
协议,8035
表示要交给RARP
协议,后两者协议本喵在后面会详细介绍。
- 帧末尾是CRC校验码,用来校验数据是否正确,和校验和是一样的作用。
MAC帧协议同样要面临解包和分用的问题,它非常的简单粗暴,采用的是定长报头的方式。
目的MAC地址是6字节大小,源MAC地址也是6字节大小,帧协议协议类型字段2字节大小,末尾校验和CRC
是4字节大小,有效载荷的大小是46~1500
字节,后面本喵会将原因。
所以在解包的时候,从整个数据帧读取前14个字节,然后再从最后读取4个字节,剩下的就是有效载荷,如此就完成了解包过程。
在分用的时候,根据帧协议类型交给对应的上层协议即可,如0800
就交给网络层的IP协议去处理有效载荷。
🦺局域网转发原理
如上图所示,主机MAC1
发送了一个数据帧给MAC7
,当数据从IP层交给数据链路层后,数据链路层给数据报加上了报头,成为了数据帧,然后发送出去,这次是真正的发送出去,数据帧在网线中跑。
而局域网中存在多台主机,这些主机都和以太网相连,都能够看到以太网,故而也能看到以太网中跑的数据。
- 网络通信本质上就是进程间通信,而网络就是临界资源。
所以局域网中的所有主机都唔那个收到主机MAC1
发送的数据,每台主机在收到数据后,数据链路层会对比数据帧报头中的目的MAC地址,如果和自己的MAC地址相同,则进行解包分用交给下一层。
如果数据帧报头中的目的MAC地址和自己的MAC地址不符,那么直接在数据链路层就丢弃该数据,上层根本不知道曾经有过这个数据。
上图中,主机MAC7
在数据链路层对比发现报头中的目的MAC地址和自己的MAC地址相同,所以进行解包分用交付给网络层,然后再逐层交付到应用层。
应用层在处理完以后将响应封装并向下交付,最终交付给数据链路层,此时数据链路层将MAC1
作为目的地址,将MAC7
作为源地址,打包成数据帧后发送到以太网中,数据帧如下图:
同样的,以太网中的所有主机的数据链路层都能收到MAC7
的响应数据,只是发现目的地址和自己不符丢弃了,最终只有主机MAC1
接收了该响应,并解包分用给上层。
- 既然主机
MAC1
可以发送数据,那么其他主机也可以发送数据。
而以太网又是一个共享资源,多台主机同时向以太网中发送数据也会导致"数据不一致问题",体现在以太网中就是数据碰撞。
- 数据在以太网中是以光电信号的形式传输的,也就是一段波。
- 当不同的光电信号发生碰撞时,就会产生波的叠加或者衰减,导致原本的光电信号发生变化,进而导致数据传输出错。
而令牌环网就是为了解决数据碰撞产生的,在局域网中存在一张令牌,只有持有令牌的主机才能向网络中发生数据,就像我们多线程中的互斥锁一样。
但是主流的网络仍然是以太网,以太网采用碰撞检测和碰撞避免的算法来避免碰撞带来的影响。
假设主机MAC1
发送了一个数据帧,主机MAC7
也发送了一个数据帧,互相发送给对方,这两个数据帧在以太网中发生了碰撞。
- 主机
MAC1
收到主机MAC7
发送的数据后,发现CRC
校验值和主机MAC7
封装数据帧时的值不一样。- 说明该数据发生了碰撞,而主机
MAC1
自己刚刚也发生了一个数据帧,所以为了避免再次碰撞,主机MAC1
等待一段时间后再重发刚刚的数据。- 主机
MAC7
采用同样的策略。
这就是碰撞检测和碰撞避免算法的大概原理,有兴趣的小伙伴可以自行研究。
如果此时主机MAC2
不断向局域网中发送垃圾数据,并且不执行碰撞检测和碰撞避免,那么就会导致其他主机无法发送数据,一直处于碰撞检测和碰撞避免的状态。
交换机:
如上图所示,一个局域网中存在很多天主机,此时向网络中发送数据的主机也就多了起来,进而导致发生碰撞的概率增加。只要主机足够多,概率性事件就会成为必然事件。
所以在比较大的局域网中,会有交换机的存在,如上图蓝色框所示,它将局域网分成了两部分,交换机左边是一部分,右边是一部分。
假设左边的主机MAC1
向右边的主机MAC100
发生数据,这个数据在局域网中传送时,会先经过交换机,由交换机转发给主机MAC100
。
如果主机MAC1
向主机MAC2
发生数据,则不通过交换机转发,直接发送,同理交换机右边也是一样的。
当主机MAC1
向主机MAC100
发送数据时,数据帧在左边部分发生了碰撞,那么当数据经过交换机时,交换机便不再转发这个数据,而是直接丢弃。
- 交换机能识别局部碰撞,对碰撞数据不做转发。
- 交换机将局域网划分成了多个碰撞域,从而减少了局域网中的数据碰撞。
- 通常情况下局域网都不会很大。
👑认识MTU
对于以太网来说,既然会存在碰撞,那么发生的数据帧是长了好还是短了好呢?
太长和太短都不行,太短会导致数据帧无法校验,因为CRC
校验是需要数据帧中有一定数量的有效载荷的,所以MAC帧协议规定,有效载荷的长度要大于等于46字节。如果最终交付到数据链路层的有效载荷太小,小于46字节,MAC帧协议会在后面补充到46字节。
如果太长的话,数据在以太网中传输的时间就会变长,从而增加了数据碰撞的概率,也不合适,所以MAC帧协议规定有效载荷的最大值是1500字节,也被叫做以太网的最大传输单元(MTU)。
- 不同的网络类型有不同的MTU。
- 如果IP层的数据报大于MTU了,则需要分片,然后再交给数据链路层。
- 不同数据链路层的标志MTU也是不同的。
MAC帧的有效载荷在46~1500
字节的范围内也会发生碰撞啊,这样规定貌似并没有解决这个问题。
- 数据在以太网中是以光电信号的形式传输的,只要有效载荷在规定范围内,那么碰撞的概率就很小。
- 光传送速度是非常快的,我们要相信光的力量。
MTU对TCP协议的影响:
由于数据链路层MTU的限制, 对于较大的IP数据包要进行分包,将较大的IP包分成多个小包,并给每个小包打上标签,每个小包IP协议头的16位标识(id)都是相同的。
每个小包的IP协议头的3位标志字段中,第2位置为0,表示允许分片, 第3位是更多分片标志位,在上篇文章中本喵有详细介绍。
到达对端时再将这些小包按顺序重组,拼装到一起返回给传输层,一旦这些小包中任意一个小包丢失,接收端的重组就会失败。
但是IP层不会负责重新传输数据,是由TCP负责的,当TCP没有收到对方的确认应答时就会触发超时重传。
MTU对IP协议的影响就向上图快递类型对发货量的影响。发货人在东京使用的是FDDI
快递,该快递一次运输的快递上限是4200kg,发送方在IP报头中填好IP地址等内容后交给快递公司发往仓敷。
快递首先从东京发往了大阪,快递重量是4200kg,在大版换成了以太网快递公司,该快递一次运输的快递上限是1400kg,所以原本4200kg的快递需要分成三趟去发。
最终在仓敷的收件人收到的快递是3个1400kg的包裹,将这几个包裹组装后得到一个4200kg的包裹。
这个过程中,FDDI
和以太网是两个不同类型的局域网,所以MTU
也不同,将快递看成是数据,从东京到仓敷的过程需要跨越两个局域网,要通过两个局域网的转发。
如上图网络传输示意图中,从东京到大版的局域网中,MTU
是4200,从大版到到仓敷的局域网中,MTU
是1400,所以数据原本4200的数据到了大版路由器以后,被拆分成了3个1400的数据发往仓敷。
- 路由器有数据链路层和网络层俩层,网络层是主要就是IP协议,能够屏蔽网络底层的差异。
- 路由器有将IP数据报进行分片的能力。
至于具体是如何分片和组装的,感兴趣的小伙伴可以去看本喵的上篇文章。从上面这个例子中可以看出MTU
的大小决定着IP协议是否进行分片,不同局域网有着不同的MTU
,而路由器可以针对不同MTU
采取相应的对策。
MTU对DUP的影响:
如上图所示,发送端主机向MTU
为4352的FDDI
局域网中发送数据,该数据帧中,包含4324字节的UDP有效载荷,8字节的UDP报头,20字节的IP报头。
当局域网中的路由器接收到该数据帧后,发现接收主机所在的局域网为MTU = 1500
的以太网,所以在路由器中将IP数据报进行分片,如上图所示,分成了三片,然后发送给接收主机。
接收主机接收到以后,进行组装,然后将完整的数据交付给上层。
- 一旦UDP携带的数据超过1472(1500 - 20(IP首部) - 8(UDP首部)),那么就会在网络层分成多个IP数据报。
- 这多个IP数据报有任意一个丢失,都会引起接收端网络层重组失败 而且UDP没有重传机制,这就意味着这个数据丢了。
- 如果UDP数据报在网络层被分片,整个数据被丢失的概率就大大增加了。
MTU对UDP的影响和TCP类似,只是对于UDP丢包时的影响更加严重。
MTU对TCP协议的影响:
- TCP的一个数据报也不能无限大,还是受制于MTU,TCP的单个数据报有效载荷的最大消息长度,称为MSS(Max Segment Size)。
- TCP在建立连接的过程中, 通信双方会进行MSS协商,最理想的情况下,MSS的值正好是在IP不会被分片处理的最大长度(这个长度仍然是受制于数据链路层的MTU)。
- 双方在发送
SYN
的时候会在TCP头
部写入自己能支持的MSS值,然后双方得知对方的MSS值之后,选择较小的作为最终MSS。- MSS的值就是在TCP首部的40字节变长选项中(kind=2)。
如上图所示便是MSS
和MTU
之间的关系,由于IP报头和TCP报头长度固定,所以MTU
的大小直接关系到MSS
的大小。
如上图所示,使用ifconfig
可以看到当前机器所在局域网的MTU,本喵的Linux机器所在局域网的MTU = 1500字节。
🦺ARP协议
如上图所示,主机A向主机B发送数据,数据一跳一跳经过多个局域网转发,最终到达了主机B所在的局域网。
- 主机将数据交付给下一跳时,下一跳可能是主机,也可能是路由器节点。
- 前提是该数据帧一定被网络层路由过,所以才能知道下一跳要去哪里。
当数据帧第一次到达主机B所在的局域网入口路由器时,路由器就迷茫了,路由器的数据链路层解包分用后,只能从网络层中得到主机B的IP地址,但是在局域网中是通过MAC地址来识别主机的,但是路由器并不知道主机B的MAC地址。
- 要有一个过程,让路由器设备认识主机B,获取主机B的MAC地址。
此时就用到了ARP
协议,ARP不是一个单纯的数据链路层的协议,而是一个介于数据链路层和网络层之间的协议:
如上图所示,ARP协议处于数据链路层,MAC帧协议在分用的时候,可以将有效载荷分用给ARP协议,PARP协议,还有网络层的IP协议。
前面本喵讲解MAC帧协议格式的时候,报头中的协议类型字段,0800
表示IP协议,0806
表示ARP协议,8035
表示RARP协议。
👑协议格式
如上图所示便是ARP协议的格式,它的长度是固定28字节,且没有有效载荷。
- 硬件类型指链路层网络类型,1为以太网,通常情况下都是1,相当于一个固定参数。
- 协议类型指要转换的地址类型,0x0800为IP地址,通常情况下都是这个值,也相当于一个固定参数。
- 硬件地址长度对于以太网地址为6字节,也相当于是一个固定参数。
- 协议地址长度对于和IP地址为4字节,也相当于是一个固定参数。
- op字段为1表示ARP请求,op字段为2表示ARP应答。
- 发送端以太网地址和发送端IP地址,以及目的以太网地址和目的IP地址相信大家一看就动。
ARP协议的数据也并不是直接发送到局域网中,而是交付给MAC帧协议进行封装,然后再发送到局域网中:
ARP协议被交付给MAC帧协议后,给ARP协议封装了报头,如上图红色框中所示。
- 注意到源MAC地址、目的MAC地址在以太网首部和ARP请求中各出现一次。
- 对于链路层为以太网的情况是多余的,但如果链路层是其它类型的网络则有可能是必要的。
👑ARP缓存表
ARP协议建立了主机IP地址和MAC地址的映射关系:
- 在网络通讯时,源主机的应用程序知道目的主机的IP地址和端口号,却不知道目的主机的MAC地址。
- 数据包首先是被网卡接收到再去处理上层协议的,如果接收到的数据包的硬件地址与本机不符,则直接丢弃。
因此在网络通信前必须通过ARP协议获得目的主机的MAC地址。
如上图所示,主机MAC1
在收到一个数据帧以后,它只能从IP协议中找到目标主机的IP地址,并不知道目标主机的MAC地址。
所以主机MAC1
先构建一个ARP
请求,其中硬件类型,协议类型,两个长度字段都是固定参数,op
字段填1,表示这是一个ARP
请求,发送端就是自己,所以发送端MAC地址为MAC1
,发送端IP地址为IP1
,目的MAC地址并不知道,使用0xFFFFFFFFFFFF
,目的IP填IP7
。
然后交给MAC帧协议封装,MAC帧首部中MAC目的地址并不知道,所以使用0xFFFFFFFFFFFF
填充,源MAC地址就是自己的MAC1
,因为这是一个ARP
请求,所以协议类型为0806
,然后将这个数据帧发送出去。
- 局域网中,主机号都是1的IP地址是一个广播地址,如
192.168.1.255
。- 发送给广播IP地址的数据帧,局域网中的所有主机都要接收并且进行处理。
- 正常的数据帧其他主机也能看到,但是在数据链路层就丢弃了,而广播地址的不会丢弃,会交付给上层做进一步处理。
主机MAC1
广播了这个数据帧后,局域网中的所有主机都接收这个数据帧,首先在数据链路层发现这个数据帧中的MAC目的地址是0xFFFFFFFFFFFF
,它无法处理,所以解包后根据帧类型0806
交付给了上面的IP层。
IP层拿到ARP
数据以后,首先看op
字段(不考虑固定参数),发现该字段的值是1,说明这是一个ARP
请求,然后再看目的IP地址和自己主机的IP地址是否相符。
如果不符则直接抛弃,不作响应,如果相符则构建响应。此时其他主机都将这个ARP
请求抛弃了,只有主机MAC7
发现目的IP地址和自己的IP地址相符,都是IP7
,说明这是有人要获取它的MAC地址。
主机MAC7
构建ARP
响应:
此时主机MAC7
知道这是给主机MAC1
的ARP
响应,将对应字段填充好,此时是一个ARP
响应,所以op
字段是2,其他字段本喵不解释。然后交给MAC帧协议进行封装。
MAC帧协议中将头部中的目的MAC地址和MAC源地址,以及帧类型填充为0806
后,发送给主机MAC1
。
- 具体字段内容可以参照上图。
此时局域网中的所有主机仍然能看到这个数据帧,但是在数据链路层对比时发现目的MAC地址是MAC1
,所以都将其抛弃了,不再向上分用给IP层。
主机MAC1
收到这个数据帧后,通过对比自己的MAC地址和数据帧中的目的MAC地址,发现这是给自己的,所以进行解包,然后根据帧类型0806
将有效载荷分用给ARP
协议。
ARP
协议首先op
字段,发现这是一个ARP
响应,说明这是自己曾经要获取MAC地址请求的响应,然后将发送端的MAC地址MAC7
和发送端的IP地址IP7
取出来,放入ARP缓存表中。
然后在将IP层的数据交给MAC帧协议进行封装,按照ARP缓存表中的映射关系填充报头,将MAC7
填到目的MAC地址帧,再发送出去给主机MAC7
。
此时主机MAC1
就能成功将数据准确的发送给主机MAC7
,成功完成网络通信。
- 每个主机在收到
ARP
数据以后,必须先看op
字段。- 通过
op
字段可以区分这是别人向自己发起的ARP
请求,还是自己曾经发起ARP
请求的响应。
ARP
协议虽然处于数据链路层,但是它的字段内容却涉及到数据链路层(MAC地址)和网络层(IP地址),所以说它工作在数据链路层和网络层之间。
通过指令arp -a
可以查看当前机器上的ARP缓存表,如上图所示。可以看到,每一个IP地址都对应一个MAC地址,这些主机都位于一个局域网内,根据缓存表的对应关系就可以在IP层路由后准确的将数据发送到指定MAC地址处的主机上。
- 每一个节点都会有这样的一个ARP缓存表。
- 缓存表中的表项有过期时间(一般为20分钟),如果20分钟内没有再次使用某个表项,则该表项失效。
- 下次还要发ARP请求来获得目的主机的硬件地址。
我们知道,在子网划分中的规则下,只有入网的设备才有IP地址,如果某一个主机断网很久了,另一台新主机使用这个IP地址,在其他主机给这个新主机发送数据的时候,ARP缓存表中的MAC地址仍然是旧主机的MAC地址,所以这台新主机收不到数据。
所以,ARP缓存表必须每隔一段时间就更新一次,如果是第一次给某台主机发送数据,则必须先进行ARP
请求获取MAC地址。
在MAC协议帧类型中,还有一个8035
的RARP
协议,这是一个反向的ARP
协议。
有时候发送方主机可能会只知道对方的MAC地址,而不知道对方的IP地址,此时就发送一个RARP
请求,获取目标MAC地址主机的IP地址。都已经知道源MAC地址和目的MAC地址了,所以这个过程非常简单,大家可以自行解决。
RARP
协议使用的情况非常少,局域网中大部分跑的还是使用ARP
协议。
🦺回顾整个协议栈
如上图所示,便是本喵讲解整个网络协议栈主脉络。
- 主机A:
用户在应用层写好数据以后,通过HTTP或者HTTPS协议封装,将报文交付给传输层的TCP或者UDP协议。
如果是使用TCP协议,则报文被先放到了发送缓冲区中,操作系统在合适的时候将其封装并交付给网络层IP协议。如果使用的是TCP协议,则将报文封装并直接交付给网络层的IP协议。
网络层的IP协议在收到数据段后再将其封装,在IP报头中填充目的IP,源IP等字段,然后将数据报交给数据链路层的MAC帧协议。
- 路由器:
MAC帧协议将数据帧通过局域网交给下一跳路由器,路由器的数据链路层收到数据帧后进行解包分用给上层的IP协议,IP层根据目的地址进行路由,然后再将新的数据报封装重新交给数据链路层。
MAC协议再将数据报交给下一跳路由器,如此往复,最终将数据帧交到了目标主机所在的局域网路由器处。
该路由器根据ARP缓存表中的映射关系,将数据发送给目标IP对应的MAC地址处的主机。
- 主机B:
主机B的数据链路层收到数据后,通过对比发现MAC帧报头中的目的MAC地址和自己的MAC地址相符,所以进行解包,然后根据帧类型的0800
将有效载荷分用给网络层的IP协议。
IP协议发现该数据报中的目的IP地址和自己的相符,所以进行解包,去掉IP报头,根据报头中的协议类型将有效载荷分用给传输层的UDP或者TCP协议。
传输层收到数据段后,将报头解包,并且根据报头中的目的端口号,将有效载荷交给应用层的HTTP或者HTTPS协议。
应用层收到报文后,进行解包,将报头和有效载荷分离,对发送过来的数据进行处理。
这就是依靠协议栈的整个网络通信过程,每一层中的详细细节本喵都有对应的文章在详细讲解,这里仅仅是一个宏观上的描述。相信到了这一步,我们对整个协议栈的认识和理解就更加透彻了。
🦺总结
对于数据链路层,重点理解数据帧在局域网中是如何传送的,局域网中的主机又是如何处理数据帧的,以及如何通过ARP
协议获取目的主机的MAC地址,进而建立ARP缓存表的。
到次,本喵对于整个网络通信的过程便讲解完毕了,虽然讲解的协议不多,但是这些都是每一层中最重要的协议。网络是非常复杂的,充斥着多种多样的协议和规则,有兴趣的小伙伴可以继续深入了解。