6、数据链路层:帧的概念、MAC地址、CSMA/CD协议、以太网的工作原理
各位同学,今天我们来聊聊数据链路层。说实话,这是整个网络体系里我最喜欢的一层。为什么?因为它离硬件最近,又离逻辑不远,有种「在钢丝上跳舞」的感觉。
我刚开始做网络驱动开发时,总觉得数据链路层就是个「搬运工」,把IP包塞进帧里发出去就完事了。直到有一次,我在一个工业现场调试设备,发现两台机器明明物理链路是通的,就是死活不通。折腾了两天,最后发现是MAC地址冲突——两台设备出厂时烧录了相同的MAC地址。嗯,从那以后,我再也不敢小看这一层了。
6.1 帧的概念——数据链路层的「快递包裹」
数据链路层传输的基本单位,叫做帧(Frame)。你可以把它想象成一个快递包裹:里面有货物(上层数据),外面贴着快递单(头部信息),最后还有个签收回执(尾部校验)。
一个典型的以太网帧长什么样?我直接给你看结构:
+----------------+----------+----------+----------+----------------+----------+
| 前导码 (7字节) | 定界符 | 目的MAC | 源MAC | 类型/长度 | 数据 | FCS |
| | (1字节) | (6字节) | (6字节) | (2字节) | (46-1500)| (4字节) |
+----------------+----------+----------+----------+----------------+----------+
这里有几个关键点,我当年踩过坑:
- 前导码和定界符:这是物理层用的,用来同步时钟。数据链路层收到后直接扔掉,不传给上层。
- MAC地址:6字节,全球唯一。但注意,是「理论上」唯一。我遇到过厂商烧录重复的情况,后面会讲。
- 数据部分:最小46字节,最大1500字节(MTU)。如果上层数据不够46字节,要填充。为什么?因为CSMA/CD协议要求帧不能太短,后面会解释。
- FCS:帧校验序列,用CRC32算法。收到帧后重新算一遍,对不上就丢帧。
6.2 MAC地址——设备的「身份证」
MAC地址,也叫物理地址、硬件地址。48位,通常写成6组十六进制数,比如 00:1A:2B:3C:4D:5E。
前24位是OUI(组织唯一标识符),由IEEE分配给厂商。后24位是厂商自己分配的。所以理论上,全球没有两块网卡有相同的MAC地址。
但现实很骨感。我曾在项目中遇到一个奇葩问题:两台服务器在同一个广播域里,偶尔会出现丢包。抓包发现,两台服务器的MAC地址一模一样!后来查出来是某厂商的虚拟化平台克隆虚拟机时,把MAC地址也克隆了。你说坑不坑?
MAC地址有三种类型:
- 单播地址:第一个字节的最低位为0。发给单个设备。
- 多播地址:第一个字节的最低位为1。发给一组设备。
- 广播地址:全F,即
FF:FF:FF:FF:FF:FF。发给所有设备。
你想想看,当一台机器发送广播帧时,同一网段的所有设备都会收到。这就是ARP协议能工作的基础。
6.3 CSMA/CD协议——以太网的「交通规则」
CSMA/CD,全称是载波监听多点接入/碰撞检测。名字很长,但说白了就是一套「先听后说,边说边听」的规则。
我习惯用会议室来类比:
- 载波监听:说话前先听听有没有人在说。如果有人说话,你就等着。
- 多点接入:谁都可以说话,没有主席台。
- 碰撞检测:你说话的同时也要听,如果听到别人也在说,说明撞车了。立刻停止,等随机时间再试。
具体流程是这样的:
- 先监听信道。如果空闲,等一个帧间间隔(96比特时间),然后发送。
- 发送的同时持续监听。如果没检测到碰撞,发送成功。
- 如果检测到碰撞,立即停止发送,并发送一个「阻塞信号」通知所有人。
- 然后执行截断二进制指数退避算法:等待一个随机时间,再重试。
这里有个关键点:为什么帧的最小长度是64字节(46字节数据+18字节头部)?
因为要保证在发送完整个帧之前,能检测到碰撞。如果帧太短,发送完了碰撞信号才传回来,发送方就不知道撞车了。这个时间取决于网络的最大传播时延。以太网规定,最远距离2500米,最大往返时间约51.2微秒。在这个时间内,至少要发送512比特(64字节)的数据。
举个例子:10Mbps的以太网,最大传播时延25.6微秒,那么最小帧长 = 2 × 25.6μs × 10Mbps = 512比特 = 64字节。明白了吧?
6.4 以太网的工作原理——从帧到链路
以太网是目前最主流的局域网技术。它的工作原理,说白了就是「基于CSMA/CD的广播通信」。
我画了一张图,帮你理清整个流程:
这张图展示了完整的发送流程。注意看,碰撞发生后不是立即重发,而是执行退避算法。这个算法很巧妙:
- 第一次碰撞:等待0或1个时间片(512比特时间)
- 第二次碰撞:等待0~3个时间片
- 第三次碰撞:等待0~7个时间片
- ...以此类推,最多到1023个时间片
为什么要这样设计?因为碰撞越频繁,说明网络越拥堵。退避时间范围越大,能有效降低再次碰撞的概率。我当年在实验室用10台机器同时发数据,亲眼看到碰撞次数呈指数级下降,这个算法真的很优雅。
6.5 实际工作中的坑与经验
说了这么多理论,我分享几个实际工作中的案例:
现在的以太网基本都是全双工(用交换机组网),CSMA/CD基本用不上了。但如果你用集线器(HUB),或者网线只有两对线,那就是半双工,CSMA/CD依然有效。我见过有人把全双工网卡插到半双工交换机上,结果疯狂丢包。为什么?因为网卡以为可以同时收发,但交换机不行。
标准以太网帧最大1500字节,但有些设备支持9000字节的巨型帧。我在做视频传输项目时,用了巨型帧,吞吐量提升了30%。但注意,整个链路的所有设备都必须支持,否则帧会被丢弃。我曾经因为交换机没配置巨型帧,排查了整整一天。
最后,总结一下数据链路层的核心要点:
| 概念 | 核心要点 | 我的建议 |
|---|---|---|
| 帧 | 最小64字节,最大1518字节 | 抓包时先看帧长度是否合法 |
| MAC地址 | 48位,前24位是OUI | 批量采购设备时扫描MAC,避免冲突 |
| CSMA/CD | 先听后说,边说边听,碰撞退避 | 全双工环境下已废弃,但原理要懂 |
| 以太网 | 基于广播的通信,交换机隔离冲突域 | 用交换机代替集线器,性能提升明显 |
好了,这一章就到这里。数据链路层是网络通信的基石,搞懂了帧结构和MAC地址,你就能看懂大部分网络问题了。下一章我们聊聊网络层,看看IP地址是怎么在复杂的网络中找到路的。