1. 引言
在计算机网络中,数据传输难免会受到噪声、干扰等因素的影响,导致接收方收到的数据与发送方不一致,这就是所谓的传输差错 。数据链路层的重要职责之一就是差错控制,它通过一系列算法来检测甚至纠正数据传输过程中出现的错误,确保向上层提供可靠的数据传输服务。
差错控制通常分为两个层面:
- 差错检测:发现数据在传输过程中是否发生了错误;
- 差错纠正/重传:发现错误后,通过重传或纠错码恢复正确的数据。
本文将系统梳理数据链路层中常用的差错控制算法,包括检测算法与重传机制两大类。
2. 差错检测算法
2.1 奇偶校验
奇偶校验是最简单的一种差错检测方法。其核心思想是在原始数据后面附加一个校验位,使得整个数据单元中"1"的个数为奇数或偶数。
- 奇校验:保证数据中"1"的总数为奇数;
- 偶校验:保证数据中"1"的总数为偶数。
示例 :假设要传输的数据为 1011001(其中"1"的个数为 4)。
- 若采用偶校验,校验位应为
0,使"1"的总数保持偶数; - 若采用奇校验,校验位应为
1,使"1"的总数变为奇数。
局限性:奇偶校验只能检测出奇数个比特错误,当发生偶数个比特错误时(如两个比特同时翻转),校验结果仍然正确,无法发现错误,因此在实际网络中已较少单独使用。
2.2 循环冗余校验
2.2.1 基本原理
CRC的核心思想是将待发送的数据看作一个二进制多项式,然后用一个事先约定的生成多项式 G(x) 去除这个数据多项式(模 2 除法),得到的余数作为冗余码 附加在数据末尾一同发送。接收方收到数据后,用同一个生成多项式对收到的数据做模 2 除法,若余数为 0,则认为传输无差错;否则判定发生了错误。
2.2.2 模 2 除法
模 2 除法与普通除法类似,但减法是按位异或运算(相同为 0,不同为 1),不存在借位。
计算步骤:
假设数据为 101001,生成多项式为 1101(对应 x³ + x² + 1,阶数为 3)。
- 在数据末尾补
阶数个 0:101001→101001000; - 用生成多项式对补零后的数据做模 2 除法;
- 得到的余数即为冗余码,附加到原始数据后发送。
整个过程的图解如下:
#mermaid-svg-AGIjhvSMITmoKuR2{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-AGIjhvSMITmoKuR2 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-AGIjhvSMITmoKuR2 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-AGIjhvSMITmoKuR2 .error-icon{fill:#552222;}#mermaid-svg-AGIjhvSMITmoKuR2 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-AGIjhvSMITmoKuR2 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-AGIjhvSMITmoKuR2 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-AGIjhvSMITmoKuR2 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-AGIjhvSMITmoKuR2 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-AGIjhvSMITmoKuR2 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-AGIjhvSMITmoKuR2 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-AGIjhvSMITmoKuR2 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-AGIjhvSMITmoKuR2 .marker.cross{stroke:#333333;}#mermaid-svg-AGIjhvSMITmoKuR2 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-AGIjhvSMITmoKuR2 p{margin:0;}#mermaid-svg-AGIjhvSMITmoKuR2 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-AGIjhvSMITmoKuR2 .cluster-label text{fill:#333;}#mermaid-svg-AGIjhvSMITmoKuR2 .cluster-label span{color:#333;}#mermaid-svg-AGIjhvSMITmoKuR2 .cluster-label span p{background-color:transparent;}#mermaid-svg-AGIjhvSMITmoKuR2 .label text,#mermaid-svg-AGIjhvSMITmoKuR2 span{fill:#333;color:#333;}#mermaid-svg-AGIjhvSMITmoKuR2 .node rect,#mermaid-svg-AGIjhvSMITmoKuR2 .node circle,#mermaid-svg-AGIjhvSMITmoKuR2 .node ellipse,#mermaid-svg-AGIjhvSMITmoKuR2 .node polygon,#mermaid-svg-AGIjhvSMITmoKuR2 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-AGIjhvSMITmoKuR2 .rough-node .label text,#mermaid-svg-AGIjhvSMITmoKuR2 .node .label text,#mermaid-svg-AGIjhvSMITmoKuR2 .image-shape .label,#mermaid-svg-AGIjhvSMITmoKuR2 .icon-shape .label{text-anchor:middle;}#mermaid-svg-AGIjhvSMITmoKuR2 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-AGIjhvSMITmoKuR2 .rough-node .label,#mermaid-svg-AGIjhvSMITmoKuR2 .node .label,#mermaid-svg-AGIjhvSMITmoKuR2 .image-shape .label,#mermaid-svg-AGIjhvSMITmoKuR2 .icon-shape .label{text-align:center;}#mermaid-svg-AGIjhvSMITmoKuR2 .node.clickable{cursor:pointer;}#mermaid-svg-AGIjhvSMITmoKuR2 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-AGIjhvSMITmoKuR2 .arrowheadPath{fill:#333333;}#mermaid-svg-AGIjhvSMITmoKuR2 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-AGIjhvSMITmoKuR2 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-AGIjhvSMITmoKuR2 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-AGIjhvSMITmoKuR2 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-AGIjhvSMITmoKuR2 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-AGIjhvSMITmoKuR2 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-AGIjhvSMITmoKuR2 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-AGIjhvSMITmoKuR2 .cluster text{fill:#333;}#mermaid-svg-AGIjhvSMITmoKuR2 .cluster span{color:#333;}#mermaid-svg-AGIjhvSMITmoKuR2 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-AGIjhvSMITmoKuR2 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-AGIjhvSMITmoKuR2 rect.text{fill:none;stroke-width:0;}#mermaid-svg-AGIjhvSMITmoKuR2 .icon-shape,#mermaid-svg-AGIjhvSMITmoKuR2 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-AGIjhvSMITmoKuR2 .icon-shape p,#mermaid-svg-AGIjhvSMITmoKuR2 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-AGIjhvSMITmoKuR2 .icon-shape .label rect,#mermaid-svg-AGIjhvSMITmoKuR2 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-AGIjhvSMITmoKuR2 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-AGIjhvSMITmoKuR2 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-AGIjhvSMITmoKuR2 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是
否
原始数据
补零(补生成多项式阶数个 0)
模 2 除法(异或运算)
得到余数(冗余码)
拼接:原始数据 + 余数
发送至接收方
接收方再次模 2 除法
余数为 0?
数据正确,接收
检测到错误,丢弃或请求重传
2.2.3 常用生成多项式
| 标准 | 生成多项式 |
|---|---|
| CRC-8 | x⁸ + x² + x + 1 |
| CRC-16 | x¹⁶ + x¹⁵ + x² + 1 |
| CRC-CCITT | x¹⁶ + x¹² + x⁵ + 1 |
| CRC-32(以太网) | x³² + x²⁶ + x²³ + x²² + x¹⁶ + x¹² + x¹¹ + x¹⁰ + x⁸ + x⁷ + x⁵ + x⁴ + x² + x + 1 |
CRC 的检错能力很强,能检测出所有单比特错误、所有双比特错误、所有奇数个错误以及所有长度不超过生成多项式阶数的突发错误。
2.3 校验和
校验和算法常见于 IP、TCP、UDP 等网络层和传输层协议。其基本思想是将数据划分为若干固定长度的单元(如 16 位),将所有单元按二进制反码加法累加,最后取反码得到校验和。接收方将数据和校验和一起进行同样的累加,若结果全为 1,则说明数据无误。
校验和实现简单、计算开销小,但检错能力弱于 CRC,主要用于上层协议中。
3. 差错纠正与重传机制
单纯依靠检测算法只能"发现"错误,无法"修复"错误。数据链路层通过自动重传请求机制,在检测到错误后通知发送方重新发送数据,从而保证可靠传输。
3.1 停止等待 ARQ
停止等待 ARQ 是最基础的重传机制:发送方每发送一帧后就必须停下来,等待接收方的确认帧(ACK)。
工作流程:
- 发送方发送一帧数据,并启动超时定时器;
- 接收方收到帧后校验:
- 若无误,回复 ACK;
- 若出错,直接丢弃,不回复(或回复 NAK);
- 发送方在超时前收到 ACK,继续发送下一帧;
- 若超时未收到 ACK,重发该帧。
接收方 发送方 接收方 发送方 #mermaid-svg-UYyrQ0fWl8Aa3P3s{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-UYyrQ0fWl8Aa3P3s .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-UYyrQ0fWl8Aa3P3s .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-UYyrQ0fWl8Aa3P3s .error-icon{fill:#552222;}#mermaid-svg-UYyrQ0fWl8Aa3P3s .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-UYyrQ0fWl8Aa3P3s .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-UYyrQ0fWl8Aa3P3s .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-UYyrQ0fWl8Aa3P3s .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-UYyrQ0fWl8Aa3P3s .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-UYyrQ0fWl8Aa3P3s .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-UYyrQ0fWl8Aa3P3s .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-UYyrQ0fWl8Aa3P3s .marker{fill:#333333;stroke:#333333;}#mermaid-svg-UYyrQ0fWl8Aa3P3s .marker.cross{stroke:#333333;}#mermaid-svg-UYyrQ0fWl8Aa3P3s svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-UYyrQ0fWl8Aa3P3s p{margin:0;}#mermaid-svg-UYyrQ0fWl8Aa3P3s .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-UYyrQ0fWl8Aa3P3s text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-UYyrQ0fWl8Aa3P3s .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-UYyrQ0fWl8Aa3P3s .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-UYyrQ0fWl8Aa3P3s .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-UYyrQ0fWl8Aa3P3s .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-UYyrQ0fWl8Aa3P3s #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-UYyrQ0fWl8Aa3P3s .sequenceNumber{fill:white;}#mermaid-svg-UYyrQ0fWl8Aa3P3s #sequencenumber{fill:#333;}#mermaid-svg-UYyrQ0fWl8Aa3P3s #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-UYyrQ0fWl8Aa3P3s .messageText{fill:#333;stroke:none;}#mermaid-svg-UYyrQ0fWl8Aa3P3s .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-UYyrQ0fWl8Aa3P3s .labelText,#mermaid-svg-UYyrQ0fWl8Aa3P3s .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-UYyrQ0fWl8Aa3P3s .loopText,#mermaid-svg-UYyrQ0fWl8Aa3P3s .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-UYyrQ0fWl8Aa3P3s .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-UYyrQ0fWl8Aa3P3s .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-UYyrQ0fWl8Aa3P3s .noteText,#mermaid-svg-UYyrQ0fWl8Aa3P3s .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-UYyrQ0fWl8Aa3P3s .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-UYyrQ0fWl8Aa3P3s .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-UYyrQ0fWl8Aa3P3s .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-UYyrQ0fWl8Aa3P3s .actorPopupMenu{position:absolute;}#mermaid-svg-UYyrQ0fWl8Aa3P3s .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-UYyrQ0fWl8Aa3P3s .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-UYyrQ0fWl8Aa3P3s .actor-man circle,#mermaid-svg-UYyrQ0fWl8Aa3P3s line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-UYyrQ0fWl8Aa3P3s :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 帧 1 出错,丢弃 超时未收到 ACK 发送帧 0ACK 0发送帧 1重发帧 1ACK 1
特点:
- 实现简单,缓冲区开销小;
- 信道利用率低:发送方在等待 ACK 的期间处于空闲状态,不适用于高速或高延迟链路。
3.2 回退 N 帧 ARQ
为了克服停止等待 ARQ 效率低的问题,回退 N 帧 ARQ 采用流水线方式,允许发送方在未收到确认的情况下连续发送多个帧。
核心机制:
- 发送方维护一个大小为 N 的发送窗口,窗口内的帧可连续发送;
- 接收方只按序接收,若某帧出错,则丢弃该帧及之后的所有帧;
- 发送方超时后,从出错的帧开始重传窗口内所有后续帧。
示例:假设发送窗口大小为 4,发送了帧 0、1、2、3;帧 1 出错被丢弃。接收方即使正确收到了帧 2、3,也会将其丢弃。发送方超时后,从帧 1 开始重传帧 1、2、3。
这种机制应使用累计确认:ACK n 表示"帧 n 及之前的所有帧均已正确收到",减少了确认帧的数量。
特点:
- 提高了信道利用率;
- 但出错时会重传大量已经正确接收的帧,造成带宽浪费。
3.3 选择重传 ARQ
选择重传 ARQ 是回退 N 帧 ARQ 的改进版本。接收方对出错帧之后的正确帧不再丢弃,而是缓存起来,只要求发送方重传出错的那一帧。
核心机制:
- 接收方维护一个接收窗口,缓存失序但正确的帧;
- 发送方只为损坏或丢失的帧单独重传;
- 接收方收齐所有帧后,按序交付给上层。
特点:
- 带宽利用率最高,只重传真正出错的帧;
- 但接收方需要更大的缓冲区来缓存失序帧,实现复杂度更高。
4. 纠错编码:海明码
除了"检测 + 重传"的思路,还有一种思路是让接收方直接纠正 错误,即使用纠错码。海明码就是其中的代表,由 Richard Hamming 提出。
4.1 基本原理
海明码通过在数据中插入多个冗余校验位 ,使得每个校验位覆盖不同的数据位组合。当某个比特出错时,根据校验结果的组合可以定位到具体出错的比特,从而直接翻转该位完成纠正。
- 若数据位为 m 位,冗余位为 r 位,需满足:
2^r >= m + r + 1; - 例如:4 位数据需要 3 位冗余(2³ = 8 >= 4 + 3 + 1 = 8)。
4.2 计算步骤
以 4 位数据 1011 为例。由 2^r >= m + r + 1 可知:m=4 时 r=3,因此码字总长度为 7 位。
第 1 步:确定码字位置
冗余位需要放在 2 的幂次位置,即第 1、2、4 位;则数据位依次放到第 3、5、6、7 位:
位置编号:1 2 3 4 5 6 7
码字内容:_ _ 1 _ 0 1 1
第 2 步:计算冗余位的值
每个冗余位按位置编号的二进制特征,负责校验特定位置的数据位:
| 冗余位 | 所在位置 | 位置二进制 | 负责校验的位置 | 覆盖的数据位 |
|---|---|---|---|---|
| r1 | 1 | 001 | 1、3、5、7 | D1、D2、D4 |
| r2 | 2 | 010 | 2、3、6、7 | D1、D3、D4 |
| r4 | 4 | 100 | 4、5、6、7 | D2、D3、D4 |
规律是:某冗余位负责校验「位置编号二进制中对应位为 1」的所有位置。例如 r1 的二进制是 001,最低位为 1,因此它校验所有二进制最低位为 1 的位置(1、3、5、7)。
采用偶校验 计算每个冗余位,使该校验组中 1 的总数为偶数(异或和为 0):
- r1 :覆盖 D1、D2、D4 =
1、0、1,异或结果为1 ⊕ 0 ⊕ 1 = 0,因此 r1 取0; - r2 :覆盖 D1、D3、D4 =
1、1、1,异或结果为1 ⊕ 1 ⊕ 1 = 1,为凑成偶数个 1,r2 取1; - r4 :覆盖 D2、D3、D4 =
0、1、1,异或结果为0 ⊕ 1 ⊕ 1 = 0,因此 r4 取0。
最终得到的 7 位海明码为:
位置编号:1 2 3 4 5 6 7
码字内容:0 1 1 0 0 1 1
所以数据 1011 编码后的海明码是 0110011。
第 3 步:接收方校验与纠错
接收方重新计算三个校验组,得到三个校验结果 S1、S2、S4:
S1 = r1 ⊕ D1 ⊕ D2 ⊕ D4(对应位置 1、3、5、7)S2 = r2 ⊕ D1 ⊕ D3 ⊕ D4(对应位置 2、3、6、7)S4 = r4 ⊕ D2 ⊕ D3 ⊕ D4(对应位置 4、5、6、7)
如果没有错误,这三个表达式的值全为 0。
假设传输过程中第 6 位发生翻转(D3 由 1 变成 0),收到的码字变为 0110001。重新计算:
S1 = 0 ⊕ 1 ⊕ 0 ⊕ 1 = 0S2 = 1 ⊕ 1 ⊕ 0 ⊕ 1 = 1S4 = 0 ⊕ 0 ⊕ 0 ⊕ 1 = 1
将结果按 S4 S2 S1 排列得到二进制数 110,转换为十进制正好是 6,说明第 6 位出错。接收方只需把第 6 位翻转回来(0 → 1),即可恢复正确的海明码 0110011。
如果 S4 S2 S1 = 000,则说明传输无错误。这就是海明码「不仅能检错,还能定位并纠正单比特错误」的核心过程。
海明码属于前向纠错技术,适用于实时性要求高、不适合频繁重传的场景(如深空通信、实时音视频)。
5. LDPC
5.1 基本原理
LDPC(Low-Density Parity-Check,低密度奇偶校验码)由 Gallager 于 1962 年提出,但因当时硬件条件限制长期未被重视,直到后来才被重新发现并广泛应用于现代通信系统。它的核心是用一个稀疏校验矩阵 H 来描述码字:矩阵中绝大多数元素为 0,只包含少量 1,因此称为"低密度"。
以一个最简单的 (6, 3) LDPC 码为例:码字长度为 6,包含 3 个信息位和 3 个校验位。假设其校验矩阵 H 为:
v1 v2 v3 v4 v5 v6
c1 [ 1 1 0 1 0 0 ]
c2 [ 0 1 1 0 1 0 ]
c3 [ 1 0 1 0 0 1 ]
矩阵的每一行对应一个校验节点 ,每一列对应一个变量节点。第 1 行表示校验节点 c1 连接变量节点 v1、v2、v4,因此它给出的校验方程是:
c1:v1 ⊕ v2 ⊕ v4 = 0c2:v2 ⊕ v3 ⊕ v5 = 0c3:v1 ⊕ v3 ⊕ v6 = 0
也就是说,任何合法码字都必须同时满足上面三个异或方程。
LDPC 码可以通过 Tanner 图来描述变量节点与校验节点之间的关系。上例对应的 Tanner 图如下:
#mermaid-svg-IU2gjADf5c90QEhZ{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-IU2gjADf5c90QEhZ .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-IU2gjADf5c90QEhZ .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-IU2gjADf5c90QEhZ .error-icon{fill:#552222;}#mermaid-svg-IU2gjADf5c90QEhZ .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-IU2gjADf5c90QEhZ .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-IU2gjADf5c90QEhZ .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-IU2gjADf5c90QEhZ .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-IU2gjADf5c90QEhZ .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-IU2gjADf5c90QEhZ .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-IU2gjADf5c90QEhZ .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-IU2gjADf5c90QEhZ .marker{fill:#333333;stroke:#333333;}#mermaid-svg-IU2gjADf5c90QEhZ .marker.cross{stroke:#333333;}#mermaid-svg-IU2gjADf5c90QEhZ svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-IU2gjADf5c90QEhZ p{margin:0;}#mermaid-svg-IU2gjADf5c90QEhZ .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-IU2gjADf5c90QEhZ .cluster-label text{fill:#333;}#mermaid-svg-IU2gjADf5c90QEhZ .cluster-label span{color:#333;}#mermaid-svg-IU2gjADf5c90QEhZ .cluster-label span p{background-color:transparent;}#mermaid-svg-IU2gjADf5c90QEhZ .label text,#mermaid-svg-IU2gjADf5c90QEhZ span{fill:#333;color:#333;}#mermaid-svg-IU2gjADf5c90QEhZ .node rect,#mermaid-svg-IU2gjADf5c90QEhZ .node circle,#mermaid-svg-IU2gjADf5c90QEhZ .node ellipse,#mermaid-svg-IU2gjADf5c90QEhZ .node polygon,#mermaid-svg-IU2gjADf5c90QEhZ .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-IU2gjADf5c90QEhZ .rough-node .label text,#mermaid-svg-IU2gjADf5c90QEhZ .node .label text,#mermaid-svg-IU2gjADf5c90QEhZ .image-shape .label,#mermaid-svg-IU2gjADf5c90QEhZ .icon-shape .label{text-anchor:middle;}#mermaid-svg-IU2gjADf5c90QEhZ .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-IU2gjADf5c90QEhZ .rough-node .label,#mermaid-svg-IU2gjADf5c90QEhZ .node .label,#mermaid-svg-IU2gjADf5c90QEhZ .image-shape .label,#mermaid-svg-IU2gjADf5c90QEhZ .icon-shape .label{text-align:center;}#mermaid-svg-IU2gjADf5c90QEhZ .node.clickable{cursor:pointer;}#mermaid-svg-IU2gjADf5c90QEhZ .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-IU2gjADf5c90QEhZ .arrowheadPath{fill:#333333;}#mermaid-svg-IU2gjADf5c90QEhZ .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-IU2gjADf5c90QEhZ .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-IU2gjADf5c90QEhZ .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-IU2gjADf5c90QEhZ .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-IU2gjADf5c90QEhZ .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-IU2gjADf5c90QEhZ .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-IU2gjADf5c90QEhZ .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-IU2gjADf5c90QEhZ .cluster text{fill:#333;}#mermaid-svg-IU2gjADf5c90QEhZ .cluster span{color:#333;}#mermaid-svg-IU2gjADf5c90QEhZ div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-IU2gjADf5c90QEhZ .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-IU2gjADf5c90QEhZ rect.text{fill:none;stroke-width:0;}#mermaid-svg-IU2gjADf5c90QEhZ .icon-shape,#mermaid-svg-IU2gjADf5c90QEhZ .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-IU2gjADf5c90QEhZ .icon-shape p,#mermaid-svg-IU2gjADf5c90QEhZ .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-IU2gjADf5c90QEhZ .icon-shape .label rect,#mermaid-svg-IU2gjADf5c90QEhZ .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-IU2gjADf5c90QEhZ .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-IU2gjADf5c90QEhZ .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-IU2gjADf5c90QEhZ :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} v1
c1
v2
v4
c2
v3
v5
c3
v6
图中左侧为变量节点,右侧为校验节点。每个校验节点要求与其相连的变量节点异或和为 0,从而构成一组校验约束。
5.2 编码与译码
编码示例
编码时,根据校验矩阵 H 构造生成矩阵 G,将信息位映射为满足所有校验约束的码字。实际系统中常采用系统化编码,即码字前半部分保持信息位不变,后半部分为计算出的校验位。
继续使用上面的 (6, 3) LDPC 码。信息位为 v1、v2、v3,校验位为 v4、v5、v6。根据校验方程可以反推出校验位的计算公式:
v4 = v1 ⊕ v2v5 = v2 ⊕ v3v6 = v1 ⊕ v3
假设信息位为 1 0 1,代入计算:
v4 = 1 ⊕ 0 = 1v5 = 0 ⊕ 1 = 1v6 = 1 ⊕ 1 = 0
最终得到码字 1 0 1 1 1 0。接收方收到码字后,只需重新计算三个校验方程,若结果全为 0,则说明传输无误。
置信传播译码步骤
译码是 LDPC 码的核心。接收方通常使用置信传播算法,在变量节点与校验节点之间迭代传递软信息,逐步修正错误。基本流程如下:
- 初始化:根据接收到的每个比特,计算初始概率(或对数似然比),作为变量节点的初始信息;
- 变量节点更新:每个变量节点把「来自信道的信息」和「来自校验节点的信息」合并后,传递给相连的校验节点;
- 校验节点更新:每个校验节点根据其他连接变量节点的信息,更新自己要传回的信息;
- 硬判决:根据变量节点汇总的全部信息,对每个比特做 0 或 1 的判决;
- 迭代校验:用校验矩阵检查判决结果。若所有校验方程均满足,译码结束;否则回到第 2 步继续迭代,直到满足条件或达到最大迭代次数。
继续用上面的例子说明:假设发送码字 1 0 1 1 1 0,传输过程中 v2 发生翻转,接收方收到 1 1 1 1 1 0。此时校验方程 c1 = 1 ⊕ 1 ⊕ 1 = 1,不再为 0,说明出现错误。置信传播算法会通过校验节点与变量节点之间的信息交换,逐步提高"v2 出错"的可信度,最终将其判决修正为 0,恢复正确码字 1 0 1 1 1 0。
相比海明码主要纠正单比特错误,LDPC 码通过稀疏校验矩阵和迭代译码能够纠正更多随机错误,性能可以接近香农极限。
5.3 特点与应用
- 纠错能力强,性能接近信道容量;
- 校验矩阵稀疏,适合高效存储与并行硬件实现;
- 采用迭代译码,复杂度可控。
LDPC 码已广泛应用于 Wi-Fi(802.11n/ac/ax) 、5G NR 数据信道、数字电视、深空通信等场景。与 5G 控制信道采用的 Polar 码不同,LDPC 码通常用于数据信道,因为它们适合长码块和高吞吐量场景。
6. 数据链路层差错控制的实际应用
| 协议/技术 | 采用的算法 |
|---|---|
| 以太网 | CRC-32 |
| Wi-Fi(802.11) | CRC-32 |
| HDLC / PPP | CRC-16 / CRC-CCITT |
| 蓝牙 | ARQ + CRC |
| 5G NR | LDPC 码 + Polar 码(信道编码) |
现代数据链路层普遍采用 CRC 检测 + ARQ 重传 的组合方案:CRC 负责高效地发现错误,ARQ 机制负责在发现错误后可靠地恢复数据。而在对时延极度敏感或无法回传确认的场景中,则倾向于使用海明码、LDPC 码等纠错编码。
7. 总结
数据链路层的差错控制是保障网络通信可靠性的基石。本文围绕"检测"与"纠正/重传"两条主线,梳理了以下核心内容:
- 检测算法:奇偶校验(简单但能力有限)、CRC(检错能力强、应用最广)、校验和(实现简单、用于上层协议);
- 重传机制:停止等待 ARQ(简单低效)、回退 N 帧 ARQ(流水线 + 批量重传)、选择重传 ARQ(只重传出错帧,效率最高);
- 纠错编码 :海明码可以直接定位并纠正单比特错误;LDPC 码通过稀疏校验矩阵和迭代译码实现接近香农极限的性能,适用于高可靠性通信场景。
理解这些算法的原理与适用场景,不仅有助于深入掌握数据链路层的工作原理,也为学习传输层 TCP 的可靠传输机制打下了坚实基础。