文章目录
数据链路层的作用
数据链路层最基本的服务是将源计算机网络层来的数据可靠的传输到相邻节点的目标计算机的网络层
其实,数据链路层负责的是同一个局域网的不同设备之间的通信问题
以太网
在众多数据链路中最著名,使用最广泛的莫过于以太网(Ethernet)
- “以太网” 不是一种具体的网络, 而是一种技术标准; 既
包含了
数据链路层的内容, 也包含了
一些物理层的内容. 例如: 规定了网络拓扑结构, 访问控制方式, 传输速率等 - 例如以太网中的网线必须使用双绞线; 传输速率有10M, 100M, 1000M等
- 以太网是当前应用最广泛的局域网技术; 和以太网并列的还有令牌环网, 无线LAN等
以太网帧格式
- 源地址和目的地址是指网卡的硬件地址(也叫
MAC地址
), 长度是48位,是在网卡出厂时固化的 - 帧协议类型字段有三种值,分别对应I
P、ARP、RARP
- 帧末尾是
CRC校验码
MAC地址
- MAC地址用来
识别数据链路层中相连的节点
- 长度为
48位
, 即6个字节
. 一般用16进制数字加上冒号的形式来表示(例如: 08:00:27:03:fb:19) - 在网卡出厂时就确定了,
不能修改
. mac地址通常是唯一的
(虚拟机中的mac地址不是真实的mac地址, 可能会冲突; 也有些网卡支持用户配置mac地址)
MTU
MTU相当于发快递时对包裹尺寸的限制. 这个限制是不同的数据链路对应的物理层, 产生的限制
- 以太网帧中的数据长度规定
最小46字节,最大1500字节
,ARP数据包的长度不够46字节,要在后面补填充位
- 最大值1500称为
以太网的最大传输单元
(MTU),不同的网络类型有不同的MTU - 如果一个数据包从以太网路由到拨号链路上,数据包长度大于拨号链路的MTU了,则需要对数据包进行
分片
(fragmentation)不同的数据链路层标准的MTU是不同的
MTU对IP协议的影响
由于数据链路层MTU的限制, 对于较大的IP数据包要进行分包
- 将较大的IP包
分成多个小包
, 并给每个小包打上标签 - 每个小包IP协议头的 16位标识(id) 都是相同的
- 每个小包的IP协议头的3位标志字段中, 第
2位置为0
, 表示允许分片,第3位来表示结束标记
(当前是否是最后一个小包, 是的话置为1, 否则置为0) - 到达对端时再将这些小包, 会按顺序重组,
拼装到一起
返回给传输层 - 一旦这些小包中任意一个小包丢失, 接收端的重组就会失败. 但是IP层不会负责重新传输数据
比方说有一个IP数据报,总长度大于1500字节,那么这个IP数据报中的有效载荷就会被分成N份
被分成N份的IP数据报中的16位标识是完全相同
的,表示这N份数据报其实是同一个IP数据报
3位标志位中的第一个比特位为0
,第二个比特位为0,表示可以分片
,也就是说,只要IP报文的3位标志位中的第二位为0,就表示这个报文是被分片的
被分片的每片报文的偏移量都是不一样的,通过偏移量可以确定报文分片前的原始位置
,也可以通过偏移量来确认是否有分片的报文在传输过程中丢失了
分片后的报文被传输到对端主机后就会进行组装,这时就能通过偏移量和IP报文总长度确定组装的顺序
分片报文的前面部分的3位标志位的第三个比特位都是1,表示更多分片
,也就是这个分片后面还有分片
,而分片的最后一个报文第三个比特位是0,表示更多分片位是0,也就是没有更多分片,这个分片就是分片的最后一个
通过偏移量和总长度,还有更多分片标志位,就能确认这个被分片的IP报文是否丢包,并且可以按照顺序组装,交付给上层
分片和组装的过程都是在网络层完成的,上层和下层并不知道IP报文被分片和组装过
MTU对UDP协议的影响
- 一旦UDP携带的数据超过1472(1500 - 20(IP首部) - 8(UDP首部)), 那么就会在网络层分成多个IP数据报
- 这多个IP数据报有任意一个丢失, 都会引起接收端网络层重组失败. 那么这就意味着, 如果UDP数据报在网络层被分片, 整个数据被丢失的概率就大大增加了
MTU对于TCP协议的影响
- TCP的一个数据报也不能无限大, 还是
受制于MTU
. TCP的单个数据报的最大消息长度, 称为MSS(MaxSegment Size) - TCP在建立连接的过程中, 通信
双方会进行MSS协商
- 最理想的情况下,
MSS的值正好是在IP不会被分片处理的最大长度
(这个长度仍然是受制于数据链路层的MTU) - 双方在发送SYN的时候会在TCP头部写入自己能支持的MSS值
- 然后双方得知对方的MSS值之后, 选择较小的作为最终MSS
- MSS的值就是在TCP首部的40字节变长选项中(kind=2)
MSS和MTU的关系
以太网通信细节
在一个局域网中,上层的IP数据报并不能直接发送到各个主机,上层的IP数据报会被封装成MAC帧(以太网帧)的形式在局域网中传输
比如说一个局域网中的主机A,收到了上层的IP数据报
,要把这个IP数据报发送给这个局域网
中的B主机,就得先对这个IP数据报进行封装
,添加要发送主机的MAC地址,自己的MAC地址,还有要封装的类型,再在IP数据报后面添加MAC帧的校验,然后把这个MAC帧发送到局域网内,此时局域网内的所有主机都会收到这个MAC帧
,所有主机在收到这个MAC帧
后就会对这个帧进行解析
,查看这个MAC帧的目的MAC地址,和自己的MAC地址进行对比,如果和自己的MAC地址符合,就会对这个MAC帧进行校验,如果校验没问题,就会分用这个MAC帧,拆出有效载荷交付给上层,完成数据通信。如果对比MAC帧的目的MAC帧地址后和自己的不符合,就会立即丢弃这个MAC帧,不会交付给上层
以太网通信的问题
局域网的通信资源是多个主机之间共享
的,局域网其实也可以看作是一个临界区,局域网通信资源可以看作是临界资源
以太网通信只允许一台主机和另一台主机进行数据通信
当一组主机数据通信时,另一组主机也在进行数据通信
,就会发生碰撞,这个局域网就会瘫痪,所以要保证在局域网中只有一个主机在发送数据
一个局域网
可以看作是一个碰撞域
每一个主机在发送数据时都要进行冲突检测,如果检测出冲突,就要进行冲突避免
如果检测到自己发送的数据发生了碰撞,就会进行重传MAC帧
ARP协议
上面的以太网通信,是把上层的数据报封装成MAC帧进行局域网间的通信,但是,MAC帧的报文字段中
有目的MAC地址,但是如果是第一次通信,我们只知道对方的IP地址,并不知道对方的MAC地址
,那么就无法发送MAC帧报文给想要发送的主机,所以说在进行MAC帧通信前,首先要获得想要通信主机的MAC地址
。
这时我们就可以使用ARP协议来把目标主机的IP地址转换成MAC地址
ARP不是一个单纯的数据链路层的协议
, 而是一个介于数据链路层和网络层之间的协议
ARP协议建立了主机 IP地址 和 MAC地址 的映射关系
- 在网络通讯时,源主机的应用程序知道目的主机的IP地址和端口号,却不知道目的主机的硬件地址
- 数据包首先是被网卡接收到再去处理上层协议的,如果接收到的数据包的硬件地址与本机不符,则直接丢弃
- 因此在通讯前必须获得目的主机的硬件地址
ARP数据报的格式
MAC帧不只可以封装IP数据报,也可以封装其他数据报
,ARP数据报其实就是一个封装了ARP请求/应答的MAC帧
- 以太网目的地址是目的主机的MAC地址,共6个字节,当ARP作为请求发送时并不知道,因此是全F,也就是广播发送给全部主机;当ARP作为应答回应时,以太网目的地址是请求的源主机MAC地址
- 以太网源地址就是发送ARP主机的MAC地址,也是6个字节,作为请求是源主机MAC地址,作为应答是目的主机MAC地址
- 帧类型就代表MAC帧中封装的类型
- 硬件类型是处理当前网络的链路层网络类型,当前为
以太网就是1
,占用2个字节 - 协议类型是指
要转换的地址类型
,当前要转换的是IP地址,仍然占用2个字节 - 硬件地址长度也就是MAC地址的长度,为
6个字节
,因此“6”这个数字就用一个字节就能存放了 - 协议地址长度是指当前的IP地址长度,也是用一个字节就能存放了,IPv4为
4个字节
,IPv6为16个字节 - op
为1
的话表示请求,2
表示应答 - 发送端以太网地址就是发送ARP数据报的MAC地址,也就是前面的以太网源地址,同样为6个字节的空间
- 发送端IP地址就是发送ARP数据报的主机IP地址,4个字节
- 目的以太网地址当为请求时是全F,应答时就为源主机MAC地址,6字节
- 目的IP地址当请求时为目的主机的IP地址,当为应答时就为源主机IP地址,4个字节
ARP转换过程
比如说一个局域网中的主机要发送数据给这个局域网中的另一个数据,就是把上层的数据报封装成MAC帧发送到局域网中,这时我们是第一次通信,只知道对方主机的IP地址,就要把IP地址转换成MAC帧地址。
假设有一个主机A,要给主机B发送数据,主机A有主机B的IP地址,这时要完成主机B IP地址到主机B MAC地址的转换
- 首先,主机A
构建一个ARP请求
,填充对应的数据,OP字段设置位1,代表ARP请求,目的MAC帧地址填充为全F,表示
不知道主机B的MAC地址,请求主机B回应 - 然后主机A把这个ARP请求交付给下层,把这个ARP请求封装成一个MAC帧,MAC帧的目的MAC地址填充为全F,
表示
广播发送给全部主机,帧类型填充为0806,表示
这个MAC帧里面封装的是一个ARP请求 - 主机A把这个MAC帧发送出去,所有的主机都会收到这个MAC帧,因为这个MAC帧的目的MAC地址为全F,所以所有的主机都会对这个MAC帧进行分用,提取出里面的ARP信息
- 所有的主机首先查看ARP信息里的OP字段,判断这个ARP是一个请求还是响应,如果是ARP响应,就会直接丢弃,如果是一个ARP请求,就会把ARP请求里的目的IP地址和自己主机的IP地址进行对比,如果不匹配,也会丢弃,如果匹配上的话,就会构建ARP响应回复给发送方主机
- 这时假设主机B收到的ARP请求里的目的IP地址匹配上了,主机B就会构建ARP响应,先填充固定的数据,OP字段设置为2,代表ARP响应,目的MAC地址填充收到的APR请求里的源MAC地址,也就是主机A的MAC地址
- 然后主机B把这个ARP响应交付给下层,封装成MAC帧,MAC帧的目的MAC地址填充成主机A的MAC地址,给主机A发送MAC帧
- 主机A收到MAC帧,对比目的MAC地址,发现是发送给自己的,就会
分用
,得到这个ARP响应,查看OP字段,发现是响应,这时主机A就会拿到响应里的发送端MAC地址 - 至此,主机A就完成了主机B的IP地址转换为主机B MAC地址的过程
APR缓存
在局域网内,并不是每次发送数据都需要封装ARP请求取获取对方的MAC地址,而是获取一次以后就会有一个ARP缓存表,把目标主机的MAC地址和IP地址的映射关系保存起来
,下次发送数据就不必再发送APR请求再获取对方的MAC地址了,而是直接查表
使用arp -a
命令来查看Linux系统中的ARP缓存表
这个缓存表并不是永久有效的,因为ARP缓存表维护机制中存在不完善的地方,当主机收到一个ARP的应答包后,它并不验证自己是否发送过这个ARP请求
,而是直接将应答包里的MAC地址与IP对应的关系替换掉原有的ARP缓存表里的相应信息
。这就是导致ARP欺骗的根本原因。
ARP缓存表过一段时间就会清除,然后重新发起ARP请求获取对方的MAC地址