Appearance
封装成帧与透明传输
2026 大纲 三(一)数据链路层的功能与三(二)组帧。链路层功能的通论在本篇第一节;差错控制的具体算法在《差错检测》与《海明码》,流量控制与可靠传输机制在《三种 ARQ 协议对比》。
一、物理层交上来的是一串没有结构的比特
上一章末尾,集线器把好几个网段的比特混成了一个冲突域。但即使不谈冲突,物理层交给上层的东西本身就很难用——它只保证"电平送过去了",别的一概不管:
| 物理层不管的事 | 不管会怎样 | 由链路层的哪项功能兜住 |
|---|---|---|
| 这串比特从哪开始、到哪结束 | 接收方无法切出可交付的数据单元 | 封装成帧(帧定界) |
| 中间某一位被噪声翻转了 | 错误数据被当作正确数据交给网络层 | 差错控制 |
| 发送方比接收方快,接收缓存被灌爆 | 后到的数据直接被丢弃,发送方毫不知情 | 流量控制 |
| 一条广播信道上多个站同时发 | 信号互相碰撞,全部报废 | 介质访问控制 |
数据链路层这一整章就是在补这张表。 前三项在任何链路上都要考虑,第四项只在共享信道(总线型以太网、无线局域网)上才出现——点对点链路两端只有两个站,不存在争用,所以 PPP 完全没有介质访问控制部分。
本节负责第一项:先把边界切出来,否则后面三项无从谈起——不知道一帧从哪到哪,就没法对"一帧"算校验、没法给"一帧"编号、也没法说"这一帧发生了碰撞"。
三个词先分清:链路=一段无源物理线路,中间无交换节点;数据链路=物理链路加上控制传输所需的协议(软硬件通常做在网卡里);帧=链路层的 PDU。
向上承诺了什么:三档服务
链路层向网络层提供的服务分三档,档次由要不要确认和要不要先建连接两个开关组合而成:
| 服务 | 确认 | 连接 | 承诺什么 | 用在哪 |
|---|---|---|---|---|
| 无确认的无连接 | 否 | 否 | 只承诺"发出去了",帧丢了不重传 | 误码率很低的有线链路;实时通信——迟到的数据不如不要 |
| 有确认的无连接 | 是 | 否 | 每帧单独确认、超时重传,帧与帧互不相干 | 误码率较高的链路(802.11) |
| 有确认的面向连接 | 是 | 是 | 建立连接 → 传送数据 → 释放连接,保证不丢、不重、按序 | 质量差且要求可靠的链路 |
两个开关本该有四种组合,但没有"无确认的面向连接"这一档——建立连接的全部意义就是承诺按序、不丢、不重,而这些只能靠确认兑现。承诺了却不确认,等于什么都没承诺。
"链路管理"就是第三档里建立、维持、释放连接这套动作,无连接的协议(以太网、PPP)没有这一步。
现代互联网对此区别对待:有线链路质量好,链路层不使用确认与重传,纠错留给 TCP(以太网、PPP);无线链路质量差,链路层自己做可靠传输(802.11)。这也解释了一个常见困惑:教材在链路层讲的停止-等待、GBN、SR,现实中的以太网一个都不用——那几个协议讲的是可靠传输的一般原理,真正大规模使用它们的是 TCP。
二、封装成帧
封装成帧就是在一段数据前后分别添加首部和尾部构成一个帧,接收端据首尾标记从比特流中识别帧的起止。首尾承担两类信息:帧定界(首尾存在的第一理由)与控制信息(地址、协议字段、序号、校验序列)。
帧定界符还有第二个作用容易被忽略:识别残帧。只有开始符、没有结束符的一段,判定为发送中断留下的半截帧,直接丢弃。
MTU 是帧数据部分的长度上限,不是帧总长。 以太网 MTU 是 1500 字节,满载帧
三、四种组帧方法
四种方法看着并列,其实按一条判据分成两组:定界依据会不会与数据本身撞车。
| 方法 | 定界依据 | 面向 | 开销 | 会与数据撞车吗 | 主要短板 |
|---|---|---|---|---|---|
| 字符计数法 | 首部的总字节数字段 | 字节 | 一个长度字段 | 不会,天然透明 | 计数出错则永久失步 |
| 字符填充法 | SOH / EOT 字节 | 字节 | 每个冲突字节 +1 字节 | 会 → ESC 转义 | 只能按字节处理 |
| 零比特填充法 | 01111110 | 比特 | 每 5 个连续 1 插 1 比特 | 会 → 5 个 1 后插 0 | 需逐位扫描 |
| 违规编码法 | 物理层非法波形 | 比特 | 0 | 不会,天然透明 | 绑定特定物理层编码 |
不撞车的两种天然透明(字符计数法、违规编码法),代价在别处;撞车的两种必须付出填充与转义的代价,换来的是与物理层编码解耦。下面把四种各自的关键点说清。
字符计数法:为什么它危险得多
它的死穴是计数字段一旦出错就永久失步——它没有可以重新扫描的锚点。设四个帧的计数依次是 5、5、8、8,第二帧的计数 5 被翻成 7:
正确的流: [5]a b c d | [5]e f g h | [8]i j k l m n o | [8]p q r s t u v
出错的流: [5]a b c d | [7]e f g h [8]i | 接收方把 j 当成下一帧的计数字段从这里开始之后所有帧的边界全部错位,而且永远回不来。另外三种只要再扫到一个定界标志就重新同步了,所以字符计数法很少单独使用。
字符填充法:ESC 为什么必须转义自身
用控制字符 SOH(0x01)标记首部开始、EOT(0x04)标记帧结束——它们是控制字符的名称,不是 S、O、H 三个字母,各占 1 字节。数据是可打印文本时不会出事,是二进制内容时某个字节完全可能恰好是 0x04。转义规则:
第三条不是"更严谨",而是必需:不转义 ESC 自身的话,数据 ESC EOT 与数据 EOT 会编码成同一个串,编码不再可逆。有了它,接收端的规则可以统一成一句:遇到 ESC 就删掉它,无条件把紧跟的下一个字节当作数据。
PPP 在异步链路上用的就是这套,只是符号换成 0x7E / 0x7D,且被转义的字节还要额外与 0x20 异或——多这一步是因为异步串口链路上某些控制字符会被中间设备(调制解调器、串口驱动)截获并解释,根本传不到对端;把它们的值统一抬到 0x20 以上就没有这个问题。
以 0x41 0x7E 0x7D 0x03 0x42 为例:
| 原始字节 | 是什么 | 处理规则 | 送上线路 |
|---|---|---|---|
| 0x41 | 可打印字符 'A' | 无需处理 | 0x41 |
| 0x7E | 与标志字段撞车 | 换成 2 字节序列 | 0x7D 0x5E |
| 0x7D | 与转义符自身撞车 | 换成 2 字节序列 | 0x7D 0x5D |
| 0x03 | ASCII 控制字符(小于 0x20) | 前加 0x7D,本字节 +0x20 | 0x7D 0x23 |
| 0x42 | 可打印字符 'B' | 无需处理 | 0x42 |
三条规则其实是同一条:
零比特填充法:为什么卡 5 不卡 6
用 01111110(0x7E,Flag)同时作帧的开始与结束标志,它的特征是正中间有 6 个连续的 1。规则是:发送方扫描数据字段,每发现连续 5 个 1 就在其后填一个 0;接收方每遇到连续 5 个 1 就删除紧跟其后的那个 0。 PPP 在同步链路(SONET/SDH)上用的就是它,HDLC 也是。
为什么卡 5 而不是卡 6? 因为填充必须发生在越界之前。卡 6 的话那 6 个 1 已经上了线路,接收方扫到第 6 个 1 时就已宣布帧结束,插在后面的 0 来不及起作用。
接收方为什么不会误删数据里本来就有的 0? 因为规则是对称的:两边在同一串比特上以同样方式数 5 个 1,接收方要删的那一位一定就是发送方刚插进去的那一位,插一次删一次严格一一对应。
走一遍就清楚了。数据 1011 1111 1111 0101,逐位扫描,维护一个"当前连续 1 的个数"计数器,数满 5 就插 0 并把计数器清零:
| 步骤 | 读入位 | 连续 1 计数 | 动作 | 累计输出 |
|---|---|---|---|---|
| 1 | 1 | 1 | 原样输出 | 1 |
| 2 | 0 | 0 | 原样输出,计数清零 | 10 |
| 3–7 | 1 1 1 1 1 | 1 → 5 | 原样输出,数满 5:插入一个 0,计数清零 | 10111110 |
| 8–12 | 1 1 1 1 1 | 1 → 5 | 原样输出,数满 5:插入一个 0,计数清零 | 10111110111110 |
| 13 | 0 | 0 | 原样输出 | 101111101111100 |
| 14 | 1 | 1 | 原样输出 | 1011111011111001 |
| 15 | 0 | 0 | 原样输出 | 10111110111110010 |
| 16 | 1 | 1 | 原样输出 | 101111101111100101 |
第 2 步为什么要清零:连续性一旦被 0 打断,之前攒的 1 就不能再累计,否则会在没有 5 连 1 的地方乱插 0。
原始 16 位 → 填充后 18 位,共插入 2 个 0:111111,一处也不该有。
反向还原:从线路上收到 101111101111100101,同样逐位扫描,数满 5 个 1 就删掉紧跟的那一位:1 0 11111 [0] 11111 [0] 0 1 0 1 → 删掉两个方括号里的 0 → 1011111111110101,与原始数据一致。
值得停一下的地方:第二个被删的 0 后面紧跟着数据本身的一个 0,线路上是 ...11111 0 0 101。接收方为什么不会多删一个?因为删完第一个 0 之后 1 的连续计数已经清零,第二个 0 只会让计数保持 0,不触发任何删除动作。
违规编码法
利用物理层编码里"合法数据不会出现"的信号组合定界:曼彻斯特编码规定每个码元中间必有一次跳变,"高-高""低-低"这种没有中间跳变的波形就是不可能与数据混淆的标志。IEEE 802.4 令牌总线用过这种方法。它零开销、天然透明,代价是绑死在特定的物理层编码上——换一种编码这套定界就失效了。
四、透明传输到底是什么意思
"透明"不是"什么都没加",而是"加了但上层看不出来"。填充与转义确实让帧变长了,但插入与删除对网络层不可见,网络层交下来什么、对端网络层就拿到什么——这就叫透明。教材的说法是"某一个实际存在的事物看起来却好像不存在一样"。
由此也就清楚了谁需要透明传输:只有用特殊标志定界的两种(字符填充、零比特填充)才需要额外做文章;字符计数法与违规编码法的定界依据与数据不会撞车,天然透明。
最后划清一条与下一节的界线:CRC 校验通过 ≠ 可靠传输。CRC 只带来无比特差错;帧丢失、帧重复、帧失序这三类里一个比特都没错,CRC 一概查不出。可靠传输 = 检错 + 编号 + 确认 + 重传,后三样是本章第四节往后的事。
本节小结
- 链路层存在的理由是物理层只交付一串无结构比特:不切边界、不查错、不控速。组帧解决边界、差错控制解决比特翻转、流量控制解决速率失配;共享信道上再加介质访问控制。向上的服务分三档,没有"无确认的面向连接"这一档。
- 组帧就是在数据前后加首尾,首尾的第一职责是帧定界。四种方法的分水岭是定界依据会不会与数据撞车:字符计数法与违规编码法不会撞车、天然透明,但前者一旦计数出错就永久失步、后者绑死特定编码;字符填充法与零比特填充法用特殊标志定界,必然撞车,于是派生出转义与位填充。
- 两种填充的核心推导各一句:ESC 必须转义自身,否则编码不可逆;零比特填充卡在 5 个 1 而非 6 个,因为填充必须发生在越界之前,而收发对称的计数规则保证"插一个、删一个"严格一一对应。透明传输的含义是任意比特组合都能原样通过链路层,插入与删除对上层不可见。
考点速记
本节在真题里被考过的形式只有一种,但它是链路层最规整的手算题之一:
给一段数据,问零比特填充后送上线路的比特串(cn-2013-37)。题面说"HDLC 协议采用零比特填充法",数据是 01111100 01111110。动作就是本节第三部分那张走查表——逐位扫,数满 5 个 1 插一个 0:
原始: 0 11111 0 0 0 11111 1 0
↑ (第 6 位起是 5 个 1,插 0)
输出: 0 11111[0] 0 0 0 11111[0] 1 0
分组: 01111100 00111110 10两个坑都在这道题里:一是数满 5 就插、不能等到 6 个;二是插入的 0 后面紧跟着数据本身的 0,输出里会出现连续两个 0(01111100 0...),看着像多插了一个,其实第二个 0 是原数据的。自查一次就够——填充后的串里不该出现 111111。
反向那一问(给线路上的串还原原始数据)历年没考过,但动作完全对称,值得一起练:数满 5 个 1 就删掉紧跟的那一位。
本节其余内容——三档服务、MTU、字符计数法的失步、违规编码法——在真题里不单独成题,但它们是判断题的常见素材,也是后面几节的前提:没有"无确认的面向连接"这一条在服务分类题里出现过;MTU 是数据部分上限不是帧总长在IP 分片那节要直接用。
易错:零比特填充数满 5 个 1 就插 0,不是 6 个。 填充必须发生在越界之前——凑够 6 个 1 时标志已经上了线路。
易错:填充是对"信息字段"做的,标志字段本身不填充。 帧首尾那两个
01111110就是要保持 6 个 1 的原样,不然接收方认不出边界。
易错:ESC(转义符)自己也必须被转义,否则编码不可逆。这不是可选的严谨,是正确性要求。
易错:MTU 指的是帧的数据部分上限。 以太网 MTU 1500 B 对应的满载帧是 1518 B,两个数不能混用。
易错:CRC 通过只说明"无比特差错",不等于可靠传输。 帧丢失、帧重复、帧失序这三类里一个比特都没错。
教材出处
- 谢希仁《计算机网络》(第 8 版)p73(3.1.1 数据链路和帧):给出"链路 / 数据链路"之分与点对点通信三步——"节点 A 的数据链路层把网络层交下来的 IP 数据报添加首部和尾部封装成帧","若节点 B 的数据链路层收到的帧无差错,则从收到的帧中提取出 IP 数据报交给上面的网络层;否则丢弃这个帧"。同页 3.1.2 节点明链路层的三个基本问题是"封装成帧、透明传输和差错检测"。
- 同书 p74(1. 封装成帧):封装成帧的定义、帧定界的作用,以及 MTU 的口径——"每一种链路层协议都规定了所能传送的帧的数据部分长度上限——最大传送单元 MTU"。同页给出 SOH(0x01)、EOT(0x04)是控制字符的名称而非字母。
- 同书 p75(2. 透明传输):透明的定义——"某一个实际存在的事物看起来却好像不存在一样","在数据链路层透明传送数据表示无论什么样的比特组合的数据,都能够按照原样没有差错地通过这个数据链路层";并给出字节填充/字符填充的转义规则与"转义字符也出现在数据当中时仍在其前面插入一个转义字符"。同页还说明帧定界符可用于识别中断产生的残帧。
- 同书 p78:区分"无比特差错"与"无传输差错"——"数据链路层使用 CRC 检验,能够实现无比特差错的传输,但这还不是可靠传输",并列出帧丢失、帧重复、帧失序三类非比特差错;同页给出互联网对有线/无线链路"区别对待"的现行做法。
- 同书 p81(3.2.2 PPP 帧格式):PPP 异步方式的字节填充三条规则(0x7E→0x7D 0x5E、0x7D→0x7D 0x5D、小于 0x20 的控制字符前加 0x7D 并改变编码,如 0x03→0x7D 0x23),以及零比特填充的做法——"只要发现有 5 个连续 1,则立即填入一个 0……可以保证在信息字段中不会出现 6 个连续 1"。
相关知识
计算机网络体系结构|差错检测(CRC 校验)|海明码校验与纠错|PPP 协议|三种 ARQ 协议对比