数据链路层基础:成帧、差错检测与 MAC
链路层大概是整个网络栈里最容易被后端开发"跳过"的一层——它不像 HTTP 那样天天打交道,也不像 TCP 那样常出现在面试题里。但你有没有想过这样一个怪问题:你的机器明明配好了 IP、ping 网关也通,可某天就是发不出包;或者整个机房的局域网突然集体变慢、ARP 表一片混乱。这些现象的根,往往就埋在链路层。
物理层只负责把 0 和 1 当成电信号/光信号送出去,但裸的比特流是没法用的:接收方不知道一串比特从哪开始到哪结束,也不知道中途有没有被干扰翻转。链路层就是在物理传输之上,补齐"切出边界、检查错误、标识本跳收发方"这三件事。这一篇我们就把这三件事的机制逐一拆开——帧是怎么成形的、CRC 怎么发现错误、MAC 怎么决定一帧发给谁——再回头讲为什么这层只管"一跳"。
链路层是"每一段道路上的行车规则"。它不管你从北京到上海的全程,只管确保你在当前这一段路上能正确地从这个路口开到下一个路口。
一、为什么裸比特流不够用
先把问题摆清楚,才知道链路层在解决什么。物理层交给你的,是一长串连续的比特:...01101001011...,没有任何结构。对上层来说,这有两个致命缺陷:
- 没有边界:接收方拿到一串比特,不知道哪几位是一个完整的数据单元。就像你听到一长串没有标点、没有停顿的语音,根本不知道一句话在哪里结束。
- 没有可靠性指示:物理介质会受电磁干扰、衰减、串扰,比特可能在传输中翻转(0 变 1)。接收方拿到一串比特,完全无法判断它是不是原样到达的。
链路层的三大职责正好对应补齐这些缺陷:成帧解决边界,差错检测解决可靠性指示,MAC 寻址解决"这一跳发给谁"。下面逐个看机制。
二、成帧机制:怎么从比特流里切出一帧
成帧(framing)就是把连续比特流切成一个个有明确边界的帧(frame)。问题的核心是:接收方怎么知道一帧从哪开始、到哪结束?常见有三种机制:
- 特殊定界符:用一个特定的字节序列标记帧的开始和结束。比如以太网帧前面有"前导码 + 帧起始定界符(SFD)“,接收方一看到这个固定模式,就知道"一帧来了”。
- 长度字段:帧头里放一个字段写明"本帧总共多长",接收方先读长度,再按长度精确截取。
- 字节/比特填充:如果用特殊字符做定界符,而数据里恰好也出现了这个字符怎么办?发送方在数据里的定界符前插入一个转义字符(填充),接收方再去掉,避免数据被误判成边界。
以太网用的是"前导码同步 + 类型/长度字段"的组合。帧一旦被切出来,发送和接收双方就有了一个共同的处理单位——后面所有校验、转发、丢弃,都是以"一帧"为单位进行的。
成帧的意义在于:它把无结构的比特流,变成了一个个可被独立处理、独立校验、独立转发的数据单元。没有成帧,上层的一切操作都无从下手。
三、差错检测机制:CRC 是怎么发现错误的
帧切出来了,接下来要回答"它在路上有没有被改坏"。链路层最主流的手段是 CRC(循环冗余校验)。我们讲清它的机制,而不只是名字。
CRC 的核心思想是把数据当成一个大的二进制数,用一个双方约定好的"生成多项式"去做模 2 除法,取余数作为校验码:
- 发送方:把帧的数据部分看成一个二进制数 M,在它后面补上若干个 0(位数等于校验码长度),然后用约定的生成多项式 G 做模 2 除法,得到的余数 R 就是 CRC 校验码,附在帧尾(以太网叫 FCS,帧校验序列,4 字节)。
- 接收方:把"数据 + 收到的 CRC"整体再用同一个 G 做模 2 除法。如果传输无误,余数应该正好为 0;余数不为 0,说明帧在传输中出错了。
为什么这套机制有效?因为只要数据里有任何一位翻转,余数几乎必然变化。CRC 经过精心设计的生成多项式,能以极高概率检测出突发错误(连续多位出错),而计算又只是移位和异或,硬件做起来极快——这正是它被网卡广泛采用的原因。
这里有个关键认知:
CRC 通常只负责"检测错误",不负责"纠正错误"。以太网的做法是:CRC 校验失败,就直接把这帧丢弃,不通知任何人,更不修复。要不要重传,留给上层(如 TCP)去决定。
这解释了一个常见困惑:既然链路层会校验,为什么还需要 TCP 保证可靠?因为链路层只是"发现坏了就扔",它从不保证一定送到。可靠性是 TCP 这一层补的,链路层只提供"这一跳传输质量"的检测,且只在这一跳内有效——下一跳会重新计算 CRC。
四、MAC 地址机制:一帧到底发给谁
帧成形了、校验也有了,最后一个问题:在同一个局域网里,这帧该送给哪块网卡?这就要靠 MAC 地址。
- MAC 地址是链路层用来标识网卡接口的地址,48 位,通常写成
00:1a:2b:3c:4d:5e这样的十六进制。 - 它通常在网卡出厂时就烧录好(也可软件修改),全球理论上唯一。
- 以太网帧头里有目的 MAC 和源 MAC 两个字段。交换机靠目的 MAC 决定从哪个端口转发出去(下一篇详讲),接收网卡靠目的 MAC 判断"这帧是不是发给我的"——不是就丢弃(混杂模式除外)。
初学者最容易混淆 MAC 和 IP,这里一句话钉死它们的区别:
MAC 是本地道路上的"门牌号",只在一个二层网络内有意义,每过一跳就被换掉;IP 是跨城市的"邮寄地址",全程不变,用于整个互联网范围的寻址。 一个管"这一跳交给谁",一个管"最终送到哪"。
这也是为什么访问公网时,你的机器解析的不是"远端服务器的 MAC"(那根本传不过路由器),而是"默认网关的 MAC"——MAC 的作用范围过不了一跳路由。这个配合关系,正是下一篇 ARP 要解决的事。
五、链路层只管一跳:全局是很多段链路拼起来的
把上面三件事串起来,就能理解链路层的边界:它只保证一段链路内的传输,绝不负责端到端可靠性。
从你的电脑到远端服务器,数据实际经过的不是一条"统一大通道",而是很多段彼此独立的链路:
- 你的电脑 → 家里路由器:可能是 WiFi 或网线(以太网);
- 家里路由器 → 运营商设备:可能是光纤(PON);
- 运营商之间 → 骨干网:可能是各种广域网链路;
- 最后到服务器机房 → 又是以太网。
每一段链路可以用完全不同的链路层技术,每一段都独立成帧、独立 CRC 校验、独立用本段的 MAC 寻址。 数据每过一个路由器,旧的帧头被拆掉、CRC 被丢弃,路由器看 IP 决定下一跳,再用下一段链路的技术重新成帧、重新算 CRC、填新的 MAC。
这正是链路层和网络层必须分开的根本原因:链路层解决"每一段路怎么走",且每段路可以各不相同;网络层(IP)解决"全程要经过哪些段、整体往哪走"。一个管局部异构,一个管全局统一。
六、为什么这样设计:用"一跳"换来异构互联
为什么链路层故意只管一跳、不管全局?这是个漂亮的设计取舍。
互联网要连接的物理介质千差万别——以太网、WiFi、光纤、4G/5G、蓝牙……如果要求链路层负责端到端,那它就得理解所有这些介质的全程协作,复杂到不可能实现。
链路层的解法是把问题切小:我不管全程,我只保证"在我这一段、用我这种介质,能把一帧正确地从这头送到那头"。每种介质各自实现自己的链路层即可。然后由上面统一的 IP 层把这些异构的"一跳"串成全程。
这样带来的好处是巨大的:任何一种新的物理介质,只要实现了自己的链路层(成帧 + 差错检测 + 本跳寻址),就能无缝接入互联网,上面的 IP/TCP/HTTP 完全不用改。你的手机从 WiFi 切到 5G,链路层整个换了一套,但微信连接不断——因为变化被牢牢挡在了链路层这一跳之内。
七、和后端 / SRE 实践的联系
链路层看似离业务很远,但它的故障信号在排障里非常典型:
- “有 IP 却发不出包”:本机配了 IP,但 ARP 解析不到网关 MAC(链路层寻址失败),或网卡/交换机端口故障。这时 IP 层以上全是好的,问题在二层。
- 广播风暴 / 二层环路:交换机环路导致广播帧被无限放大,整个局域网瘫痪。表现是网络极慢、设备 CPU 飙高,
ping大量丢包。 - MAC 漂移 / ARP 抖动:虚拟化和容器环境里,同一个 MAC 在多个端口间跳动,导致交换机转发表混乱、连接时通时断。
- CRC 错误计数:交换机端口的 CRC 错误计数持续上涨,通常意味着网线老化、接口接触不良或电磁干扰——这是物理/链路层硬件问题的强信号,
ethtool -S或交换机端口统计能看到。
很多线上"网络不通/抖动"的真正根因,最初并不在应用层,而在二层。当上层全部正常却就是不通时,记得往下看一层——成帧、CRC、MAC 寻址里很可能藏着答案。
八、学习这一部分最容易踩的坑
1. 把 MAC 和 IP 混为一谈
MAC 管一跳、每跳被换掉、只在本地二层有意义;IP 管全程、基本不变、用于全网寻址。混淆这两者,后面 ARP、路由、网关全讲不通。
2. 以为链路层保证可靠传输
链路层(以太网)只做差错检测:CRC 失败就丢帧,既不修复也不重传。可靠性是 TCP 补的。"链路层会校验所以一定可靠"是典型误解。
3. 以为从源到目的是一条链路
全程是很多段异构链路拼起来的,每段独立成帧、独立 CRC、独立 MAC 寻址,数据每过一跳就重新封装一次帧。
4. 忽视 CRC 是"检测"不是"纠正"
CRC 余数不为 0 只能告诉你"这帧坏了",不能告诉你"哪一位坏了、怎么修"。以太网的选择是直接丢弃,把重传决策交给上层。
总结
这一篇我们把链路层的三大机制拆开看清楚了:
- 链路层在裸比特流之上补齐三件事:成帧(切出边界)、差错检测(CRC 发现错误)、MAC 寻址(本跳交给谁);
- 成帧靠定界符/长度字段把比特流切成可独立处理的帧,是后续一切操作的前提;
- CRC 用模 2 除法取余数做校验,只负责检测错误,以太网的策略是校验失败直接丢帧,不修复不重传;
- MAC 是本跳的"门牌号",只在二层有意义、每跳被换掉,与全程不变的 IP 分工明确;
- 链路层只管一跳,全程是很多段异构链路拼接而成,每段独立成帧、独立校验、独立寻址;
- 这种"只管一跳"的设计,换来的是任何物理介质都能无缝接入互联网的巨大灵活性。
把"成帧—校验—本跳寻址"这条主线记牢,下一篇我们就顺着 MAC 往上走,看以太网交换机是怎么靠学习 MAC 地址,把"到处广播"进化成"精准转发"的。
参考资源:
- 《计算机网络:自顶向下方法》(Kurose & Ross)
- 《计算机网络》(谢希仁)
- IEEE 802.3 - Ethernet Standard
- Wikipedia - Cyclic redundancy check