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算法。收到帧后重新算一遍,对不上就丢帧。
我的经验:调试网络问题时,第一步就是抓包看帧结构。用Wireshark打开,看FCS是否正确,看MAC地址是否匹配。很多「通而不通」的问题,都是帧结构出了问题。

6.2 MAC地址——设备的「身份证」

MAC地址,也叫物理地址、硬件地址。48位,通常写成6组十六进制数,比如 00:1A:2B:3C:4D:5E

前24位是OUI(组织唯一标识符),由IEEE分配给厂商。后24位是厂商自己分配的。所以理论上,全球没有两块网卡有相同的MAC地址。

但现实很骨感。我曾在项目中遇到一个奇葩问题:两台服务器在同一个广播域里,偶尔会出现丢包。抓包发现,两台服务器的MAC地址一模一样!后来查出来是某厂商的虚拟化平台克隆虚拟机时,把MAC地址也克隆了。你说坑不坑?

避坑指南:我曾经在数据中心部署时,发现新到的服务器和旧服务器MAC地址冲突。原因是厂商生产批次混乱,烧录了重复的地址。所以,批量采购设备时,一定要先扫描所有MAC地址,确认没有重复。

MAC地址有三种类型:

  • 单播地址:第一个字节的最低位为0。发给单个设备。
  • 多播地址:第一个字节的最低位为1。发给一组设备。
  • 广播地址:全F,即 FF:FF:FF:FF:FF:FF。发给所有设备。

你想想看,当一台机器发送广播帧时,同一网段的所有设备都会收到。这就是ARP协议能工作的基础。

6.3 CSMA/CD协议——以太网的「交通规则」

CSMA/CD,全称是载波监听多点接入/碰撞检测。名字很长,但说白了就是一套「先听后说,边说边听」的规则。

我习惯用会议室来类比:

  • 载波监听:说话前先听听有没有人在说。如果有人说话,你就等着。
  • 多点接入:谁都可以说话,没有主席台。
  • 碰撞检测:你说话的同时也要听,如果听到别人也在说,说明撞车了。立刻停止,等随机时间再试。

具体流程是这样的:

  1. 先监听信道。如果空闲,等一个帧间间隔(96比特时间),然后发送。
  2. 发送的同时持续监听。如果没检测到碰撞,发送成功。
  3. 如果检测到碰撞,立即停止发送,并发送一个「阻塞信号」通知所有人。
  4. 然后执行截断二进制指数退避算法:等待一个随机时间,再重试。

这里有个关键点:为什么帧的最小长度是64字节(46字节数据+18字节头部)?

因为要保证在发送完整个帧之前,能检测到碰撞。如果帧太短,发送完了碰撞信号才传回来,发送方就不知道撞车了。这个时间取决于网络的最大传播时延。以太网规定,最远距离2500米,最大往返时间约51.2微秒。在这个时间内,至少要发送512比特(64字节)的数据。

核心公式:最小帧长 = 2 × 最大传播时延 × 数据传输速率

举个例子:10Mbps的以太网,最大传播时延25.6微秒,那么最小帧长 = 2 × 25.6μs × 10Mbps = 512比特 = 64字节。明白了吧?

6.4 以太网的工作原理——从帧到链路

以太网是目前最主流的局域网技术。它的工作原理,说白了就是「基于CSMA/CD的广播通信」。

我画了一张图,帮你理清整个流程:

以太网帧发送流程 1. 封装帧 添加MAC地址、类型、FCS 2. 载波监听 信道空闲? 3. 发送帧 同时监听碰撞 4. 完成 否(碰撞) 5. 停止发送 发送阻塞信号 6. 退避等待 随机时间后重试 回到步骤2

这张图展示了完整的发送流程。注意看,碰撞发生后不是立即重发,而是执行退避算法。这个算法很巧妙:

  • 第一次碰撞:等待0或1个时间片(512比特时间)
  • 第二次碰撞:等待0~3个时间片
  • 第三次碰撞:等待0~7个时间片
  • ...以此类推,最多到1023个时间片

为什么要这样设计?因为碰撞越频繁,说明网络越拥堵。退避时间范围越大,能有效降低再次碰撞的概率。我当年在实验室用10台机器同时发数据,亲眼看到碰撞次数呈指数级下降,这个算法真的很优雅。

6.5 实际工作中的坑与经验

说了这么多理论,我分享几个实际工作中的案例:

案例1:半双工 vs 全双工
现在的以太网基本都是全双工(用交换机组网),CSMA/CD基本用不上了。但如果你用集线器(HUB),或者网线只有两对线,那就是半双工,CSMA/CD依然有效。我见过有人把全双工网卡插到半双工交换机上,结果疯狂丢包。为什么?因为网卡以为可以同时收发,但交换机不行。
案例2:巨型帧(Jumbo Frame)
标准以太网帧最大1500字节,但有些设备支持9000字节的巨型帧。我在做视频传输项目时,用了巨型帧,吞吐量提升了30%。但注意,整个链路的所有设备都必须支持,否则帧会被丢弃。我曾经因为交换机没配置巨型帧,排查了整整一天。
避坑指南:我曾经在调试一个嵌入式设备时,发现它发送的帧FCS总是错误。用示波器一看,原来是CPU处理速度跟不上,发送完数据后FCS还没算完。解决方案是启用硬件CRC计算,或者降低发送速率。所以,写驱动时一定要确认硬件是否支持自动计算FCS。

最后,总结一下数据链路层的核心要点:

概念 核心要点 我的建议
最小64字节,最大1518字节 抓包时先看帧长度是否合法
MAC地址 48位,前24位是OUI 批量采购设备时扫描MAC,避免冲突
CSMA/CD 先听后说,边说边听,碰撞退避 全双工环境下已废弃,但原理要懂
以太网 基于广播的通信,交换机隔离冲突域 用交换机代替集线器,性能提升明显

好了,这一章就到这里。数据链路层是网络通信的基石,搞懂了帧结构和MAC地址,你就能看懂大部分网络问题了。下一章我们聊聊网络层,看看IP地址是怎么在复杂的网络中找到路的。


交易系统化学习资料 微信Strategy888888