差错编码
数据链路层能够提供的可能服务包括差错检测,甚至是差错纠正,它们的基础是进行差错编码。差错编码的基本原理:在发送节点,使用差错检测和纠正比特(Error-Detection and-Correction, EDC)来增强数据 D D D,记 D → D R D\rightarrow DR D→DR。在接收节点,仅接收到比特序列 D ′ R ′ D'R' D′R′, D ′ D' D′ 和 R ′ R' R′ 可能和初始的 D D D 和 R R R 不同。接收方的挑战是在它只收到 D ′ D' D′ 和 R ′ R' R′ 的情况下,确定 D ′ D' D′ 是否与初始的 D D D 相同。
即使采用差错编码,也还是可能有未检出比特差错,所以差错编码不能保证100%可靠。
奇偶校验码
差错检测最简单的方式就是用单个奇偶校验位(parity bit)。假设要发送的信息 D D D 有 d d d 个比特。在奇校验中,发送方只需要添加一个附加的比特,选择它的值,使得这 d + 1 d+1 d+1 个比特中 1 1 1 的个数总是为奇数;在偶校验中,发送方也只需要添加一个附加的比特,使得这 d + 1 d+1 d+1 个比特中 1 1 1 的个数总是为偶数。下图给出了 1 比特奇校验的例子,单个校验比特位于一个单独的字段中。
1 比特校验位可以检测出奇数位差错,检测不出偶数位差错。如果在采用奇校验方案中 1 1 1 的个数为偶数,那么接收方知道出现了奇数个比特差错;如果发生了偶数个比特差错,这就会出现未检出的差错。如果比特差错的概率小,而且比特之间的差错可以被看作是独立发生的,在一个分组中多个比特同时出错的概率将是极小的,在这种情况下,单个奇偶校验位可能是足够的了。然而,测量表明差错经常以“突发”的方式聚集在一起,而不是独立发生的,在突发差错的情况下,使用单比特校验位漏检率能够达到 50%。
下图展示了二维奇偶校验(二维偶校验)的一般化方案,这里 D D D 中的 d d d 个比特被划分为 i i i 行 j j j 列,为每行和每列添加奇偶校验位,产生的 i + j + 1 i+j+1 i+j+1 个奇偶校验比特构成了链路层帧的差错检测比特。
二维奇偶校验可以检测奇数位差错和部分偶数位差错。使用这种二位奇偶校验方案,包含比特值改变的列和行的校验值都可能会出现差错,因此接收方有时还可以利用存在奇偶校验差错的行和列的索引来实际识别发生差错的比特并纠正它!上图显示了一个例子,其中位于 (2,2) 的 1 出现差错变为了 0,该差错就是一个在接收方可检测并可纠正的差错。
Internet 校验和
发送方将数据的字节视为 16 比特的整数,进行校验和计算:计算所有整数的和,进位加在和的后面(溢出回卷),将得到的值按位求返,得到校验和,将校验和放入分组的校验和字段。
接收方将所有的 16 比特的整数(包括校验和)加在一起,如果该报文段中没有引入差错,则显然在接收方处该和将是 1111111111111111
(虽然和为 1111111111111111
也可能有错误);如果这些比特中存在 0,那么在传输过程中肯定出现了差错。
虽然 Internet 校验和提供差错检测,但它对差错恢复无能为力。
循环冗余校验码(CRC)
循环冗余检测(Cyclic Redundancy Check, CRC)编码,也称为多项式编码(polynomial code),是一种检错能力更强大的差错编码,广泛应用于实际网络(以太网,802.11 WiFi,ATM)。
CRC 的编码操作如下。考虑 d d d 比特的数据 D D D,发送节点要将它发送给接收节点:
-
发送方和接收方首先必须协商一个 r + 1 r+1 r+1位的比特模式,记为 G G G,其最高有效位的比特(最左边)是 1。
-
发送方要选择 r r r 位的 CRC 比特 R R R,并将它们附加到 D D D 上,使得到的 d + r d+r d+r 比特模式(被解释为一个二进制数)用模 2 算数恰好能被 G G G 整除。
-
接收方用 G G G 去除接收到的 d + r d+r d+r 比特。如果余数为非零,接收方知道出现了差错;否则认为数据正确被接收。
所有 CRC 计算采用模 2 算数来做,在加法中不进位,在减法中不借位,所以这两种操作等价于操作数的按位异或(XOR)。现在回到发送方怎么计算
R
R
R 这个关键问题上来。我们要求出的
R
R
R 使得
G
G
G 能够除以
D
⋅
2
r
XOR
R
D\cdot 2^r\ \textbf{XOR}\ R
D⋅2r XOR R 而没有余数,即应满足:
D
⋅
2
r
XOR
R
=
n
⋅
G
D\cdot 2^r\ \textbf{XOR}\ R=n\cdot G
D⋅2r XOR R=n⋅G对上述等式的两边都用
R
R
R 异或,得到:
D
⋅
2
r
=
n
⋅
G
XOR
R
D\cdot 2^r=n\cdot G\ \textbf{XOR}\ R
D⋅2r=n⋅G XOR R 这个等式告诉我们,如果我们用
G
G
G 来除
D
⋅
2
r
D\cdot 2^r
D⋅2r,余数值刚好是我们要找的
R
R
R。也就是说,我们可以这样计算
R
R
R:
R
=
r
e
m
a
i
n
d
e
r
D
⋅
2
r
G
R=remainder\frac{D\cdot 2^r}{G}
R=remainderGD⋅2r下图说明了在
D
=
101110
,
d
=
6
,
G
=
1001
,
r
=
3
D=101110,d=6,G=1001,r=3
D=101110,d=6,G=1001,r=3 的情况下的计算过程。