news 2026/10/17 5:59:56

数据链路层深度解析:帧结构、差错控制与流量控制实战指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
数据链路层深度解析:帧结构、差错控制与流量控制实战指南

1. 为什么数据链路层值得单独拎出来讲第二遍

很多人学网络,学到数据链路层就开始犯迷糊。物理层好歹能看见网线、光纤、网卡这些实物,网络层有IP地址这个抓手,传输层有端口号可以对应到具体应用。唯独数据链路层,夹在中间,既不像物理层那么"硬",也不像网络层那么"逻辑",学完之后脑子里只剩下一堆名词:帧、MAC、CRC、CSMA/CD、PPP、HDLC……然后就没有然后了。

我当初也是这么过来的。第一次学数据链路层,感觉就是背了一堆协议名字,考试能做题,但真到了抓包分析、排查网络故障的时候,完全用不上。后来做了一些底层网络相关的项目,被现实反复教育之后,才慢慢理解了这个层次的设计精髓。所以这次Part Two,我不打算按教科书的顺序把知识点再罗列一遍,而是想从"一个从业者真正需要理解什么"这个角度,把数据链路层里那些容易混淆、容易忽略、但实际工作中又特别重要的东西讲透。

这篇文章适合谁看?如果你正在学计算机网络,课本上数据链路层那一章翻来覆去看了好几遍还是觉得散,那这篇能帮你把零散的知识点串成一条线。如果你已经工作了,平时要抓包、要配交换机、要排查二层环路,那这篇里关于帧结构、差错控制、流量控制的实操细节应该对你有用。如果你只是好奇"数据链路层到底在干嘛",那也没关系,我会尽量用生活化的类比把原理讲清楚。

核心关键词我先摆出来:数据链路层、帧、MAC地址、差错控制、流量控制、可靠传输、滑动窗口、CSMA/CD、PPP协议、以太网。这些词你会在下面的内容里反复看到,但我不会干巴巴地解释定义,而是把它们放到具体的场景里去理解。

2. 数据链路层的核心问题:它到底在解决什么

2.1 从"一条链路"说起

要理解数据链路层,先得理解"链路"这个词。物理层解决的是"信号能不能在介质上传输"的问题,比如电压高低、光脉冲有无、频率怎么调制。但物理层不管传的东西对不对,也不管发送方和接收方速度是否匹配。这就好比两个人打电话,物理层保证的是"电话线是通的,声音能传过去",但至于你说的话对方听没听清、有没有听漏、你说话太快对方记不住,物理层一概不管。

数据链路层要解决的就是"在一条具体的链路上,如何把数据可靠地传过去"。注意这里的限定词:"一条具体的链路"。这是理解数据链路层的关键。它不负责端到端的传输,那是传输层的事;它也不负责路由选择,那是网络层的事。它只管相邻两个节点之间这一段。

打个比方:你要从北京寄一个包裹到广州,中间可能经过石家庄、郑州、武汉、长沙。网络层负责规划"北京→石家庄→郑州→武汉→长沙→广州"这条路线,而数据链路层负责的是每一段路怎么走——北京到石家庄这一段用什么车、怎么装货、怎么保证这段路上不出问题。到了石家庄,换一辆车,重新装货,再往下一段走。每一段都是独立的数据链路层传输。

这个类比里,"每一段路"就是一条链路,"换车重新装货"就是数据链路层的封装和解封装。理解了这个,你就明白为什么数据链路层不关心端到端,它只关心"这一跳"。

2.2 三个核心任务

数据链路层的工作可以归纳为三个核心任务,这三个任务贯穿了所有数据链路层协议的设计。

第一个任务是成帧。物理层传的是连续的比特流,数据链路层要做的第一件事就是把这串比特流切分成一个个有意义的单元,也就是帧。为什么需要成帧?因为接收方需要知道"从哪里开始是一个新的数据单元,到哪里结束"。没有帧的边界,接收方就没办法从连续的比特流里恢复出原始的数据块。成帧的方法有好几种,比如字符计数法、字符填充法、零比特填充法、违规编码法,每种方法都有自己的适用场景和坑。

第二个任务是差错控制。信号在传输过程中可能因为各种原因出错——电磁干扰、信号衰减、时钟不同步等等。数据链路层需要能够检测出这些错误,并且在必要时进行纠正或重传。这里就涉及到校验码的设计,比如奇偶校验、CRC循环冗余校验。CRC是实际应用中最常见的,以太网帧尾部的FCS字段就是CRC校验码。

第三个任务是流量控制。发送方和接收方的处理速度可能不一样。如果发送方发得太快,接收方的缓冲区满了,后来的帧就会被丢弃。流量控制就是让发送方知道什么时候该发、什么时候该停。这里涉及到滑动窗口机制,以及停等协议、后退N帧协议、选择重传协议等不同的实现方式。

这三个任务不是孤立的,它们相互配合。成帧提供了差错控制和流量控制的基本单元,差错控制保证了帧的正确性,流量控制则决定了帧的发送节奏。

2.3 可靠传输到底可不可靠

这里有一个特别容易混淆的点:数据链路层的"可靠传输"和传输层的"可靠传输"有什么区别?

数据链路层的可靠传输,指的是在一条链路上保证帧不丢、不重、不错序。它通过确认和重传机制来实现。但问题是,如果每一条链路都做可靠传输,端到端的可靠性是不是就自然保证了?不一定。因为中间节点可能出问题,比如路由器缓存溢出、处理错误等等。而且,如果每条链路都做重传,效率会很低。

所以实际中,数据链路层的可靠传输并不是必须的。以太网就不做可靠传输,它只做差错检测,检测到错误的帧直接丢弃,重传的事交给上层(通常是TCP)。而无线链路(比如Wi-Fi)因为误码率比较高,就会在数据链路层做一些重传。PPP协议在默认情况下也不做可靠传输,但在某些配置下可以启用。

理解这一点很重要:数据链路层的可靠传输是一个可选项,不是必选项。选择做还是不做,取决于链路的特性和上层的需求。

3. 帧结构深度拆解:从以太网帧说起

3.1 以太网帧的字段逐个看

以太网帧是实际工作中最常见的帧格式,抓包的时候看到的绝大多数都是它。一个标准的以太网帧(Ethernet II格式)长这样:

字段长度作用
前导码7字节用于时钟同步,让接收方准备好
帧起始定界符1字节标记帧的开始
目的MAC地址6字节接收方的物理地址
源MAC地址6字节发送方的物理地址
类型/长度2字节标识上层协议(如0x0800表示IPv4)
数据46-1500字节上层传下来的数据
帧校验序列4字节CRC校验码

前导码和帧起始定界符严格来说不算帧的一部分,它们是在物理层加的,用于接收方同步时钟。真正被数据链路层处理的是从目的MAC地址到FCS这一段。

目的MAC地址和源MAC地址各6字节,这是MAC地址的标准长度。MAC地址的前3字节是OUI(组织唯一标识符),由IEEE分配给厂商;后3字节由厂商自行分配。所以理论上MAC地址应该是全球唯一的,但实际上可以通过软件修改,所以不能完全依赖MAC地址来做安全控制。

类型/长度字段2字节,在Ethernet II格式中表示上层协议类型。常见的值有:0x0800表示IPv4,0x0806表示ARP,0x86DD表示IPv6,0x8100表示VLAN标签。如果这个字段的值小于等于1500,则表示数据字段的长度,这是IEEE 802.3格式的用法。实际中Ethernet II占绝对主导。

数据字段最少46字节,最多1500字节。为什么最少是46?因为以太网帧的总长度最少要64字节(不含前导码),减去18字节的头部和尾部,数据字段最少就是46字节。如果上层数据不足46字节,需要填充到46字节。为什么最少要64字节?这跟CSMA/CD的碰撞检测有关——帧太短的话,发送方可能在检测到碰撞之前就已经发完了,导致碰撞无法被检测到。

FCS字段4字节,用的是CRC-32校验。发送方计算帧的CRC值填入FCS,接收方重新计算并比对。如果不一致,说明帧在传输过程中出错了,直接丢弃。

3.2 帧的封装与解封装过程

当上层(网络层)把一个IP数据报交给数据链路层时,数据链路层要做的事情是:

  1. 在IP数据报前面加上目的MAC地址、源MAC地址、类型字段
  2. 如果数据不足46字节,填充到46字节
  3. 计算CRC,填入FCS字段
  4. 加上前导码和帧起始定界符(这一步通常在网卡硬件里完成)
  5. 交给物理层发送

接收方的过程正好相反:

  1. 物理层收到信号,还原成比特流
  2. 通过前导码同步时钟,找到帧起始定界符
  3. 读取目的MAC地址,判断是否是自己接收(或者是广播/组播地址)
  4. 读取源MAC地址和类型字段
  5. 计算CRC,与FCS比对
  6. 如果校验通过,去掉帧头帧尾,把数据交给上层

这个过程看起来简单,但实际中有很多细节。比如,网卡在接收到帧之后,会先检查目的MAC地址。如果不是发给自己的,也不是广播或组播地址,就直接丢弃,不会交给上层处理。这个过滤是在硬件层面完成的,效率很高。

再比如,CRC校验失败时,网卡会记录一个错误计数,但不会通知上层。上层协议(比如TCP)如果发现数据丢了,会自己触发重传。这就是为什么以太网不做可靠传输,但上层应用仍然能正常工作。

3.3 帧长度限制的由来

以太网帧的数据字段最大1500字节,这个数字不是随便定的。它跟早期的共享式以太网有关。在共享式以太网中,所有主机共享一条信道,使用CSMA/CD协议来协调发送。如果一个帧太长,发送方占用信道的时间就太长,其他主机等待的时间就太久,网络效率会下降。1500字节是在效率和灵活性之间折中的结果。

另外,帧太长的话,接收方的缓冲区可能不够用。早期的网卡缓冲区很小,1500字节是一个比较安全的数值。虽然现在网卡缓冲区已经很大了,但1500字节作为标准被保留了下来,因为改变它会导致兼容性问题。

不过,在某些场景下,我们需要传输更大的帧。比如数据中心内部,为了减少CPU中断次数、提高吞吐量,会使用巨帧(Jumbo Frame),数据字段可以达到9000字节。但巨帧需要链路两端都支持,而且中间的网络设备也要支持,否则会被丢弃或分片。

注意:如果你在抓包时发现有些帧的长度超过1518字节(不含前导码),那很可能是巨帧。但如果你的网络设备不支持巨帧,这些帧会被丢弃,导致连接异常。

4. 差错控制:CRC是怎么工作的

4.1 从奇偶校验到CRC

最简单的差错检测方法是奇偶校验。发送方在数据后面加一个校验位,使得整个数据(包括校验位)中1的个数为奇数(奇校验)或偶数(偶校验)。接收方收到后重新计算,如果不满足奇偶性,就说明出错了。

奇偶校验的问题很明显:它只能检测出奇数个比特错误,如果同时有2个比特出错,奇偶性不变,就检测不出来。而且它只能检测错误,不能定位错误,更不能纠正错误。

CRC(Cyclic Redundancy Check,循环冗余校验)比奇偶校验强大得多。它的原理是基于多项式除法。发送方和接收方约定一个生成多项式G(x),发送方把数据看作一个多项式,除以G(x),得到的余数就是CRC校验码。接收方用同样的方法计算,如果余数为0,说明传输正确。

CRC的数学原理这里不展开,你只需要知道:CRC能检测出所有单比特错误、所有双比特错误、所有奇数个错误,以及大多数突发错误。CRC-32(生成多项式为0x04C11DB7)能检测出所有长度不超过32位的突发错误,对于更长的突发错误,检测概率也非常高。

4.2 CRC的计算过程

假设我们要发送的数据是1101011011,生成多项式是10011(对应x^4 + x + 1)。计算步骤如下:

  1. 在数据后面补4个0(生成多项式的最高次幂是4),得到11010110110000
  2. 用这个数除以生成多项式10011,做模2除法(异或运算,不借位)
  3. 得到的余数就是CRC校验码

模2除法的过程:

11010110110000 10011 -------- 10011 10011 ----- 00001 00000 ----- 00010 00000 ----- 00101 00000 ----- 01011 00000 ----- 10110 10011 ----- 01010 00000 ----- 10100 10011 ----- 01110 00000 ----- 11100 10011 ----- 1110 <- 余数

所以CRC校验码是1110,发送的完整数据是11010110111110。

接收方收到后,用同样的生成多项式去除,如果余数为0,说明没有错误。

实际中CRC是用硬件实现的,速度非常快。网卡在发送和接收时都会自动计算CRC,不需要CPU干预。

4.3 差错控制的实际策略

检测到错误之后怎么办?有两种策略:纠错和检错重传。

纠错需要足够的冗余信息来定位并纠正错误。比如海明码,通过多个校验位的组合,可以定位出错的比特位置并纠正。但纠错的冗余开销比较大,而且只能纠正有限个错误。在实际的数据链路层中,纠错用得比较少,主要用在无线通信等误码率较高的场景。

检错重传是更常见的策略。接收方检测到错误后,直接丢弃出错的帧,然后通过某种机制通知发送方重传。以太网用的就是这种策略——检测到CRC错误就丢弃,不通知发送方,让上层协议(如TCP)去处理重传。

这里有一个重要的设计哲学:把复杂性放在该放的地方。数据链路层只做简单的检错,重传交给传输层。这样数据链路层的实现可以很简单,效率也更高。如果每一层都做可靠传输,整个协议栈会变得非常复杂,而且性能会下降。

实操心得:在排查网络故障时,如果发现大量CRC错误,通常意味着物理层有问题——网线质量差、接口接触不良、电磁干扰严重等等。这时候不要急着去查协议配置,先检查物理连接。

5. 流量控制与滑动窗口:让发送方和接收方步调一致

5.1 为什么需要流量控制

发送方和接收方的处理速度可能不一样。发送方可能是一台高性能服务器,发送速度很快;接收方可能是一台低功耗设备,处理速度慢。如果发送方不管不顾地发,接收方的缓冲区很快就会满,后来的帧只能被丢弃。

流量控制的目的就是让发送方知道接收方还能接收多少数据,从而调整发送速度。这就像倒水一样,如果杯子快满了,倒水的人就要慢一点或者停一下。

流量控制和拥塞控制容易混淆。流量控制是点对点的,关注的是接收方的处理能力;拥塞控制是全局的,关注的是整个网络的负载情况。数据链路层的流量控制是前者,传输层的流量控制和拥塞控制则两者都有。

5.2 停等协议:最简单的流量控制

停等协议是最简单的流量控制机制。发送方发一帧,然后停下来等确认。接收方收到后,如果校验正确,就发一个ACK;如果校验错误,就发一个NAK或者什么都不发。发送方收到ACK后才发下一帧,收到NAK或者超时后就重传。

停等协议的效率很低。假设链路往返时间(RTT)是10ms,帧的发送时间是1ms,那么发送方每11ms才能发一帧,信道利用率只有1/11≈9%。如果RTT更大,利用率会更低。

但停等协议也有优点:实现简单,接收方不需要复杂的缓冲区管理。在一些对效率要求不高、但对简单性要求高的场景下,停等协议仍然有用。

5.3 滑动窗口:提高效率的关键

滑动窗口机制允许发送方在收到确认之前连续发送多个帧。窗口大小决定了发送方可以连续发送多少个帧而不需要等待确认。

发送方的窗口里有三种状态:已发送已确认、已发送未确认、未发送。随着确认的到来,窗口向前滑动,新的帧可以进入窗口被发送。

接收方也有一个窗口,表示它可以接收的帧的序号范围。接收方通过确认报文告诉发送方自己的窗口大小,发送方据此调整发送速度。

滑动窗口的核心参数是窗口大小。窗口越大,发送方可以连续发送的帧越多,信道利用率越高。但窗口太大也有问题:接收方需要更大的缓冲区,而且一旦出错,重传的数据量也更大。

5.4 后退N帧与选择重传

基于滑动窗口,有两种经典的重传策略:后退N帧(Go-Back-N)和选择重传(Selective Repeat)。

后退N帧的策略是:接收方只按序接收帧,如果收到乱序的帧,就丢弃,并且对最后一个按序收到的帧发送确认。发送方如果超时没有收到某个帧的确认,就从这个帧开始重传所有后续帧。

举个例子:发送方发了0、1、2、3、4号帧,接收方收到了0、1,然后2丢了,收到了3、4。接收方丢弃3、4,对1发送确认。发送方超时后,从2开始重传2、3、4。

后退N帧的优点是接收方不需要缓存乱序的帧,实现简单。缺点是重传的数据量大,效率低。

选择重传的策略是:接收方可以接收乱序的帧,并缓存起来。发送方只重传那些没有收到确认的帧。

同样的例子:发送方发了0、1、2、3、4,接收方收到了0、1,2丢了,收到了3、4。接收方缓存3、4,对0、1发送确认,对2发送NAK。发送方只重传2。接收方收到2后,把2、3、4一起交给上层。

选择重传的效率更高,但接收方需要更大的缓冲区来缓存乱序的帧,实现也更复杂。

特性后退N帧选择重传
接收方缓冲区不需要缓存乱序帧需要缓存乱序帧
重传数据量大(从丢失帧开始全部重传)小(只重传丢失帧)
实现复杂度简单复杂
适用场景误码率低、窗口小误码率高、窗口大

注意:滑动窗口的窗口大小不是随便定的。对于后退N帧,窗口大小不能超过2^n - 1(n是序号位数);对于选择重传,窗口大小不能超过2^(n-1)。这是为了保证不会出现序号混淆。

6. 介质访问控制:共享信道上的秩序维护

6.1 为什么需要介质访问控制

当多条链路共享同一个传输介质时,就需要一套规则来决定谁可以发送、什么时候发送。这就是介质访问控制(MAC)要解决的问题。

共享介质的情况在早期以太网中很常见——所有主机连在一根同轴电缆上,任何一台主机发送的信号都会传到所有主机。如果两台主机同时发送,信号就会碰撞,导致数据损坏。CSMA/CD就是为解决这个问题而设计的。

现在,共享式以太网已经被交换式以太网取代。交换机为每台主机提供独立的信道,不需要争抢。但在无线网络中,介质访问控制仍然非常重要,因为无线电波是共享的。

6.2 CSMA/CD的工作原理

CSMA/CD(Carrier Sense Multiple Access with Collision Detection,载波监听多路访问/碰撞检测)的工作流程可以概括为"先听后说,边说边听,冲突停止,随机重发"。

先听后说:发送方在发送之前先监听信道。如果信道忙,就等待;如果信道空闲,就发送。

边说边听:发送方在发送过程中持续监听信道,检测是否发生碰撞。

冲突停止:如果检测到碰撞,立即停止发送,并发送一个干扰信号(Jamming Signal),让所有主机都知道发生了碰撞。

随机重发:停止发送后,等待一个随机时间,然后重新尝试发送。等待时间用二进制指数退避算法计算:第i次碰撞后,从0到2^i - 1中随机选一个数,乘以争用期(2τ),就是等待时间。

CSMA/CD的效率取决于网络负载。负载轻时,碰撞少,效率高;负载重时,碰撞频繁,效率急剧下降。所以CSMA/CD适合负载较轻的网络。

6.3 二进制指数退避算法

二进制指数退避算法是CSMA/CD的核心。它的基本思想是:碰撞次数越多,说明网络越拥挤,等待时间就应该越长,以减少再次碰撞的概率。

具体算法:

  1. 第一次碰撞后,从{0, 1}中随机选一个数k,等待k × 2τ
  2. 第二次碰撞后,从{0, 1, 2, 3}中随机选一个数k,等待k × 2τ
  3. 第i次碰撞后,从{0, 1, ..., 2^i - 1}中随机选一个数k,等待k × 2τ
  4. 如果碰撞次数超过16次,放弃发送,报告错误

2τ是争用期,也就是信号在网络上往返一次的时间。对于10Mbps以太网,2τ规定为51.2μs,对应512比特的发送时间。这就是为什么以太网帧最少要64字节——如果帧太短,发送方可能在检测到碰撞之前就已经发完了。

6.4 无线网络的介质访问控制

无线网络的介质访问控制比有线网络复杂得多。主要问题是隐蔽站问题和暴露站问题。

隐蔽站问题:A和C都能和B通信,但A和C之间互相听不到。如果A和C同时向B发送,就会在B处碰撞,但A和C都检测不到碰撞。

暴露站问题:B向A发送,C想向D发送。C听到了B的发送,以为信道忙,就等待。但实际上C的发送不会影响B和A的通信,C的等待是多余的。

为了解决这些问题,无线网络通常使用CSMA/CA(Collision Avoidance,碰撞避免)而不是CSMA/CD。CSMA/CA通过预约机制来避免碰撞:发送方先发送一个RTS(Request to Send)帧,接收方回复CTS(Clear to Send)帧,其他主机听到CTS后就知道信道被预约了,会等待一段时间再尝试发送。

CSMA/CA不能完全避免碰撞,但可以大大减少碰撞的概率。而且无线网络通常还会使用确认机制,确保帧被正确接收。

7. 常见问题与排查技巧实录

7.1 帧校验错误排查

问题现象:抓包时发现大量CRC错误,或者网络性能不稳定,时断时续。

排查思路:

  1. 检查物理连接:网线是否老化、接口是否松动、水晶头是否压好
  2. 检查电磁干扰:网线是否靠近强电源线、是否有大功率设备在旁边
  3. 检查网卡:网卡是否故障、驱动是否正常
  4. 检查交换机端口:端口是否故障、是否有大量错误计数

解决方法:更换网线、重新压水晶头、远离干扰源、更换网卡或交换机端口。

实操心得:CRC错误通常不是协议问题,而是物理层问题。我遇到过好几次CRC错误,最后发现都是网线的问题。有一次是一根网线被椅子轮子压了很久,内部线芯断了但外皮没破,导致信号时好时坏。所以排查CRC错误时,先换一根网线试试,往往能快速定位问题。

7.2 二层环路问题

问题现象:网络突然变得极慢,交换机指示灯疯狂闪烁,CPU利用率飙升。

排查思路:

  1. 检查网络拓扑,看是否有环路
  2. 查看交换机的MAC地址表,看是否有MAC地址漂移
  3. 查看交换机的CPU利用率

解决方法:启用STP(生成树协议),或者手动断开环路。

二层环路是数据链路层最危险的问题之一。因为以太网帧没有TTL字段,一旦形成环路,帧会在环路中无限循环,迅速耗尽网络带宽和交换机资源。STP通过逻辑上断开某些端口来消除环路,同时保留冗余路径。

注意:STP的收敛时间比较长(默认30-50秒),在这段时间内网络可能不通。如果需要快速收敛,可以使用RSTP(快速生成树协议),收敛时间可以缩短到几秒。

7.3 帧长度异常问题

问题现象:抓包时发现超长帧或超短帧。

排查思路:

  1. 超长帧:检查是否启用了巨帧,两端配置是否一致
  2. 超短帧:检查是否有碰撞碎片,或者网卡故障

解决方法:统一巨帧配置,更换故障网卡。

超短帧(小于64字节)通常被称为"runt frame",往往是因为碰撞导致的碎片。如果大量出现,说明网络碰撞严重,需要检查网络负载和CSMA/CD的工作情况。

7.4 常见问题速查表

问题现象可能原因排查方法解决方法
CRC错误多物理层问题检查网线、接口、干扰源更换网线、远离干扰
网络极慢二层环路检查拓扑、MAC地址表启用STP、断开环路
超长帧巨帧配置不一致检查两端配置统一巨帧配置
超短帧碰撞碎片检查网络负载降低负载、检查CSMA/CD
帧丢失缓冲区溢出检查接收方缓冲区增大缓冲区、流量控制
MAC地址漂移环路或攻击检查MAC地址表启用STP、端口安全

8. 从理论到实践:一个完整的帧传输案例

8.1 场景描述

假设有两台主机A和B,通过一台交换机连接。A要向B发送一个HTTP请求,请求数据大小为100字节。我们来跟踪整个数据链路层的过程。

8.2 发送方A的处理过程

  1. 应用层生成HTTP请求,交给传输层
  2. 传输层加上TCP头部(20字节),交给网络层
  3. 网络层加上IP头部(20字节),交给数据链路层
  4. 数据链路层加上以太网头部(14字节)和FCS(4字节),总长度 = 100 + 20 + 20 + 14 + 4 = 158字节
  5. 数据字段长度 = 100 + 20 + 20 = 140字节,大于46字节,不需要填充
  6. 计算CRC,填入FCS字段
  7. 加上前导码和帧起始定界符,交给物理层发送

8.3 交换机的处理过程

  1. 交换机从端口收到帧,读取源MAC地址,学习到MAC地址表
  2. 读取目的MAC地址,查找MAC地址表
  3. 如果找到对应的端口,就从该端口转发;如果找不到,就广播到所有端口(除了接收端口)
  4. 转发之前,交换机可能会更新FCS(因为某些字段可能被修改,比如VLAN标签)

8.4 接收方B的处理过程

  1. 网卡收到帧,检查目的MAC地址是否是自己
  2. 计算CRC,与FCS比对
  3. 如果校验通过,去掉以太网头部和FCS,把数据交给网络层
  4. 网络层检查IP头部,确认是发给自己的,去掉IP头部,交给传输层
  5. 传输层检查TCP头部,确认端口号,去掉TCP头部,交给应用层
  6. 应用层收到HTTP请求

8.5 关键观察点

在这个案例中,有几个值得注意的地方:

第一,帧的长度是158字节,在64-1518字节的范围内,是合法的以太网帧。

第二,数据字段140字节,大于46字节,不需要填充。如果HTTP请求很小,比如只有10字节,那么数据字段只有10+20+20=50字节,仍然大于46字节,不需要填充。但如果应用层数据只有1字节,数据字段就是1+20+20=41字节,小于46字节,需要填充5字节。

第三,交换机在转发时可能会修改帧。比如,如果端口配置了VLAN,交换机会在源MAC地址和类型字段之间插入4字节的VLAN标签,帧的长度变成162字节。接收方收到后,交换机会去掉VLAN标签,恢复成原来的帧。

第四,CRC校验是在每一段链路上独立进行的。A发送时计算CRC,交换机收到后校验,然后重新计算CRC(如果修改了帧),B收到后再校验。每一段链路都有自己的CRC,互不影响。

实操心得:在抓包分析时,要注意抓包点在哪里。如果是在A上抓包,看到的是A发出的帧;如果是在交换机上抓包,看到的可能是被修改过的帧(比如带了VLAN标签);如果是在B上抓包,看到的是B收到的帧。不同抓包点看到的帧可能不一样,分析时要特别注意。

9. 一些容易被忽略的细节

9.1 MAC地址与IP地址的关系

MAC地址是数据链路层的地址,IP地址是网络层的地址。两者配合工作,但作用范围不同。

MAC地址是"本地"的,只在一条链路上有效。当帧经过路由器时,源MAC地址和目的MAC地址都会改变——源MAC变成路由器的MAC,目的MAC变成下一跳的MAC。而IP地址在端到端的传输过程中保持不变(除非经过NAT)。

这就像寄快递:IP地址是最终收件人的地址,MAC地址是每一段运输中司机的联系方式。每经过一个中转站,司机换了,但收件人的地址不变。

9.2 帧的最小长度与碰撞检测

前面提到,以太网帧最少64字节。这个规定跟CSMA/CD的碰撞检测有关。

在CSMA/CD中,发送方需要在整个帧的发送过程中持续监听信道,以便检测碰撞。如果帧太短,发送方在检测到碰撞之前就已经发完了,就无法检测到碰撞。

为了保证发送方能在发送完毕之前检测到碰撞,帧的发送时间必须大于等于信号在网络上往返一次的时间(2τ)。对于10Mbps以太网,2τ=51.2μs,对应的比特数是512bit=64字节。所以帧最少要64字节。

对于更高速率的以太网,比如100Mbps、1000Mbps,2τ不变(因为信号传播速度不变),但发送64字节的时间变短了。为了解决这个问题,高速以太网要么使用全双工模式(不需要CSMA/CD),要么使用载波延伸(Carrier Extension)技术,把帧的发送时间人为延长。

9.3 PPP协议的特点

PPP(Point-to-Point Protocol,点对点协议)是数据链路层中另一个重要的协议,主要用于拨号连接和专线连接。

PPP的特点包括:

  • 支持多种上层协议(IP、IPX等)
  • 支持差错检测,但不支持纠错
  • 不保证可靠传输(默认情况下)
  • 支持身份验证(PAP、CHAP)
  • 支持多链路捆绑

PPP的帧格式和以太网不同,它使用标志字段(0x7E)来定界,使用字节填充来避免标志字段出现在数据中。PPP没有MAC地址,因为它是点对点的,不需要地址。

PPP在实际中主要用于广域网连接,比如家庭宽带拨号(PPPoE)、企业专线等。虽然现在以太网占主导地位,但PPP在某些场景下仍然不可替代。

9.4 数据链路层的"透明传输"

透明传输是数据链路层的一个重要概念。所谓透明,就是不管数据是什么样的比特组合,都能正确传输,不会因为数据中出现了控制字符而出现问题。

比如,PPP用0x7E作为帧的起始和结束标志。如果数据中恰好出现了0x7E,接收方就会误以为帧结束了。为了解决这个问题,PPP使用字节填充:在数据中出现的0x7E前面插入一个转义字符0x7D,同时把0x7E变成0x5E。接收方收到后,遇到0x7D就把后面的字符异或0x20,还原出原始数据。

以太网不需要透明传输,因为以太网帧的长度是固定的(或者由类型字段指示),不依赖特殊字符来定界。但以太网帧有最小长度限制,如果数据太短需要填充,这也是一种透明传输的机制。

注意:透明传输的实现方式取决于具体的协议。PPP用字节填充,HDLC用零比特填充,以太网用长度字段。理解不同协议的透明传输机制,有助于在抓包时正确解析帧的内容。

10. 我个人在实际操作中的体会

数据链路层的内容看起来杂,但核心就是三件事:成帧、差错控制、流量控制。把这三件事理解了,其他的协议细节都是在这三个框架下展开的。

我刚开始学的时候,总是纠结于各种协议的细节,比如CSMA/CD的退避算法具体怎么算、PPP的帧格式每个字段是什么。后来发现,这些细节当然重要,但更重要的是理解"为什么需要这些机制"。比如,为什么以太网帧最少64字节?因为要保证碰撞检测。为什么PPP要做字节填充?因为要实现透明传输。理解了"为什么",细节就自然记住了。

另外,数据链路层和物理层的界限有时候比较模糊。比如前导码,严格来说是在物理层加的,但它服务于数据链路层的帧同步。再比如CRC校验,计算是在数据链路层做的,但实际实现是在网卡硬件里。学习的时候不用太纠结于界限,重要的是理解整个流程。

最后分享一个排查问题的思路:遇到网络问题,先分层。物理层的问题(网线、接口、信号)占大多数,数据链路层的问题(CRC错误、环路、MAC地址冲突)次之,网络层以上的问题相对较少。从下往上排查,往往能更快定位问题。

这个内容后续还可以这样扩展:一是深入讲一下VLAN和STP,这两个是交换式以太网的核心技术;二是讲一下无线局域网的数据链路层,特别是802.11的帧结构和CSMA/CA的具体实现;三是讲一下数据链路层的安全问题,比如MAC地址欺骗、ARP欺骗等。这些内容在实际工作中都很常见,值得单独拿出来讲。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/17 5:59:50

深入理解BVH:从包围体到光线追踪加速的核心算法

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/17 5:58:59

Seaborn三大核心函数:histplot、scatterplot、boxplot实战精要

1. 为什么是这三个函数&#xff1f;——从真实项目场景反推Seaborn的“核心三角”你有没有过这种经历&#xff1a;打开Jupyter Notebook&#xff0c;想画个图分析数据&#xff0c;结果在Seaborn文档里翻了二十分钟&#xff0c;光是catplot、relplot、displot、jointplot、pairp…

作者头像 李华
网站建设 2026/10/17 5:58:36

基于MP2642GR-Z与ATmega1284的两串电池被动均衡方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/17 5:58:15

gmapping地图重置实战:从杀进程到根治坐标系漂移与旧图残留

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/17 5:57:56

jQuery筛选系统实战:DOM显隐驱动的高性能过滤方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/17 5:57:56

程序设计第7讲OJ作业:高频题型、常见陷阱与AC自查清单

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华