3. 物理层与数据链路层:以太网帧结构、MAC地址、CSMA/CD协议、交换机工作原理

各位同学,今天我们聊聊网络最底层的两兄弟——物理层和数据链路层。说实话,很多搞了几年开发的朋友,对这两层的理解还停留在“网线插上去就能通”的阶段。但实际工作中,恰恰是这些底层细节,决定了你的网络到底稳不稳。

我个人习惯把这两层放在一起讲,因为它们在以太网里配合得太紧密了。物理层负责把比特流变成电信号或光信号扔到线上去,数据链路层则负责把这些比特组织成有意义的“帧”,还要解决谁先发谁后发的问题。

3.1 以太网帧结构——数据在线上到底长什么样?

你想想看,两台电脑之间传数据,总不能光着屁股把比特流扔出去吧?总得有个信封,告诉接收方“这是谁发的”、“发给谁”、“里面装的是什么类型的数据”。这个信封,就是以太网帧。

标准的以太网帧(IEEE 802.3)长这样:

字段 长度(字节) 说明
前导码 7 用于同步时钟,101010...的交替模式
帧起始定界符(SFD) 1 最后两位是11,表示帧正式开始
目标MAC地址 6 接收方的物理地址
源MAC地址 6 发送方的物理地址
长度/类型 2 小于1500表示长度,大于1536表示上层协议类型
数据载荷 46~1500 上层传下来的IP数据包,不够46字节要填充
帧校验序列(FCS) 4 CRC32校验,检查传输过程中有没有出错
小技巧: 抓包的时候,Wireshark 通常会把前导码和 SFD 过滤掉不显示。你看到的“Ethernet II”帧头,其实就是从目标MAC开始算的。我刚开始学抓包时,对着屏幕找了半天前导码,后来才发现是工具帮我们省掉了。

这里有个关键点:数据载荷最少46字节,最多1500字节。为什么是46?因为整个帧(从目标MAC到FCS)最短要有64字节,减去18字节的头部和尾部,剩下46。如果上层数据不够,网卡会自动填充0。

我曾经在项目里遇到过一个问题:某台设备发出来的包,Wireshark 里看到数据部分全是0,但应用层却说数据丢了。排查了半天,发现是上层协议栈传下来的数据只有20字节,网卡填充了26个0,但接收方没正确处理填充字段,直接把填充数据当成有效载荷了。嗯,这就是没按规范来。

3.2 MAC地址——网络设备的身份证

MAC地址,全称是Media Access Control Address。说白了,就是网卡出厂时烧录的一个唯一标识。48位,通常写成6组十六进制数,比如 00:1A:2B:3C:4D:5E。

前24位是厂商代码(OUI),由IEEE分配。后24位是厂商自己分配的序列号。理论上全球唯一,但实际中……嗯,你懂的,有些小厂会乱来。

避坑指南: 我曾经遇到过一批交换机,所有端口的MAC地址竟然是一样的!查了半天,发现是厂商的固件bug,把同一个MAC烧到了所有端口上。结果就是,只要两台设备同时通信,交换机就懵了——它不知道该把帧转发到哪个端口。所以,别太迷信“全球唯一”,实际部署时最好自己验证一下。

MAC地址有三种类型:

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

你想想看,当一台设备收到一个帧时,它会先看目标MAC是不是自己。如果是,就收下;如果不是,就扔掉。但如果是广播地址,所有设备都得收下——这就是广播风暴的根源。

3.3 CSMA/CD协议——老式以太网的“交通规则”

在早期的以太网里,所有设备都连在同一根同轴电缆上(总线型拓扑)。大家共用一条线,谁想发数据谁就发。但问题来了:如果两台设备同时发,信号就会在线上撞在一起,谁也收不到。

CSMA/CD 就是解决这个问题的。全称是 Carrier Sense Multiple Access with Collision Detection,翻译过来就是“载波监听多路访问/碰撞检测”。

它的工作流程,我总结成四步:

  1. 先听再说: 发送前先监听线路。如果线路空闲,就发;如果忙,就等。
  2. 边发边听: 发送过程中继续监听。如果检测到碰撞(信号电平异常),立即停止发送。
  3. 发个通知: 发送一个32位的“阻塞信号”,告诉所有设备“刚才撞了,大家注意”。
  4. 随机等待: 等待一个随机时间(退避算法),然后重新尝试。
核心要点: CSMA/CD 是“先听后说,边说边听”。它只适用于半双工模式。现在的全双工交换网络已经不需要它了,但理解它有助于你理解为什么早期以太网有距离限制——信号在线上跑需要时间,如果线太长,碰撞信号传回来时发送方已经发完了,就检测不到碰撞了。

我记得刚入行时,师傅让我排查一个网络时延大的问题。我测了半天,发现只要流量一大,丢包率就飙升。后来发现,那台老交换机还在用半双工模式,CSMA/CD 频繁触发退避,导致有效吞吐量直线下降。换成全双工后,问题立刻解决。

3.4 交换机工作原理——从“共享”到“交换”

交换机是数据链路层的核心设备。它不像集线器(Hub)那样无脑转发,而是根据MAC地址表来智能转发。

交换机的三个核心功能:

  • MAC地址学习: 每收到一个帧,就把源MAC地址和入端口记录下来,更新MAC地址表。
  • 帧转发/过滤: 查MAC地址表,如果找到目标MAC对应的端口,就只往那个端口转发;如果没找到,就广播到所有端口(除了入端口)。
  • 环路避免: 通过生成树协议(STP)防止网络环路。

下面这张图,是我自己画的交换机工作流程,你看一眼就明白了:

交换机帧转发流程 收到帧 学习源MAC地址与端口 查MAC地址表 目标MAC是否存在? 存在 单播转发 不存在 广播到所有端口 转发完成 说明:交换机通过MAC地址表实现精准转发,避免不必要的广播

交换机的MAC地址表是动态学习的。默认是空的,每收到一个帧就学一条。如果一段时间没收到某个源MAC的帧,表项就会老化删除(默认老化时间300秒)。

实战经验: 我曾经帮一家公司排查网络卡顿问题。发现核心交换机的MAC地址表里,同一个MAC地址出现在两个不同的端口上。这就是典型的“MAC地址漂移”,通常是由网络环路引起的。最后定位到是一台傻瓜交换机被人不小心用网线环接了。拔掉那根线,一切恢复正常。

交换机有三种转发模式:

模式 延迟 错误检测 适用场景
直通转发 低(几微秒) 无 内部高速网络,链路质量好
存储转发 高(整个帧收完) 完整CRC校验 广域网,链路质量差
无碎片转发 中等(收前64字节) 过滤碎片帧 混合场景

我个人习惯在生产环境里用存储转发模式。虽然延迟稍微大一点,但能过滤掉错误帧,避免坏帧在网络里扩散。你想想看,如果让一个CRC校验失败的帧一路转发下去,接收方应用层拿到错误数据,那后果可比多等几微秒严重多了。

总结一下: 物理层负责把比特变成信号扔到线上,数据链路层负责把这些比特组织成帧,用MAC地址标识设备,用CSMA/CD(老式网络)或全双工(现代网络)解决冲突问题,用交换机实现智能转发。这三块内容,是理解整个TCP/IP协议栈的基石。后面的IP层、传输层,都是建立在它们之上的。