1.写在前面
在使用编码技术进行差错控制的技术中分为了 ARQ(自动请求重传)和 FEC(前向纠错)。而前向纠错不仅能发现错误还能确定具体的二进制错误位置,因而广泛使用。
前向纠错又可以分为检错编码和纠错编码。检错编码中,常用的是奇偶校验码和循环冗余校验,而纠错编码中,常用的是海明码。
2.奇偶校验码
奇偶校验时校验码中最简单的一种实现手段。它的思想就是,当采用偶(奇)校验的时候,冗余位+原始码流中 1 的个数是偶(奇)数个。
奇偶校验码只能检测出错误而无法对其修改,也无法检测偶数位错误,也就是说,如果传输的比特流中发生了两位比特的改变,那么是不知道是发生了差错的,因为改变了两位检错位就变正了
2.1偶校验
当采用偶校验的时候,原始码流中有 3 个 1 了。我需要让总的 1 的个数为偶数个,所以校验位填充 1 。
奇校验的方式相同,就是让 1 的总个数为奇数个。如上图,那么此时校验位就应该填充 0 。
2.2水平垂直奇偶校验
上面的校验码也叫水平校验码。但当我们将水平扩展到二维的时候,我们还可以对列进行校验。
上图采用水平垂直偶校验,可以观察到,列校验和行校验都是保证列和行 1 的个数总数为偶数。
note:
3.循环冗余校验
相比较于奇偶校验,循环冗余校验检错的能力更加强大,当然也相对而言稍稍复杂。
只采用 CRC 校验的数据链路层并不能实现可靠传输,因为还缺少重传机制。
基本思想
- 循环冗余校验是在原始码流后面加上一串二进制数字,生成新的帧发送出去。
- 这个二进制数是这样计算的,它是生成的新的帧,同发送方与接收方共同选定的特定的数整除的余数。(这个特定的数,又叫 CRC 生成多项式,作为除数使用),你可以在下面的实例中体会。
- 这里的整除采用的是模2运算,不进位,不借位
- 收发双方共同约定的特殊的数依照国际标准来选取。你可以在维基百科中找到这些标准。
- 校验码的个数是最高幂,且校验码都用 0 表示,此时的校验码称为临时校验码
- 原始码流作为被除数,CRC 生成多项式作为除数,得到的余数称为最终校验码,并且最终校验码的个数要和临时校验码相等,即都等于最高次幂。比如,若算出的最终校验码是 11 ,而最高次幂是 3,则在前面补 0,变成 011
- 将最终校验码填充到原始码流的后面发送出去即可
实际操作
单单是描述思想是很抽象的,下面用一个实例来讲解。
首先我们选取其中一个 CRC 生成国际标准:
G
(
X
)
=
X
4
+
X
3
+
1
G(X) = X^4 + X^3 + 1
G(X)=X4+X3+1
原始码流是 1011 0011 ,下面开始计算最终的包含 CRC 校验的新帧
- 根据 CRC 生成多项式标准,我们可以推出这个二进制除数是 11001 。
这串数字代表了 CRC 生成国际标准: G ( X ) = X 4 + X 3 + 1 G(X) = X^4 + X^3 + 1 G(X)=X4+X3+1的系数,即
X 4 , X 3 , X 0 X^4,X^3,X^0 X4,X3,X0的系数为 1,而 X 2 , X 1 X^2,X^1 X2,X1的系数为 0。
所以最终的这个二进制数就是 11001. - 由基本思想中的第 5 条规则得出,校验码的个数就是 4 个(校验码的个数是最高幂,且校验码都用 0 表示),此时临时校验码就是 0000 ,填充到原始码流,得到 1011 0011 0000(此时是临时校验码)
- 用 1011 0011 0000 除以 11001 得到余数 0100。如下图所示。
- 将余数 0100 (这就是最终的校验码校验码)填充到原始码流的后面,得到 1011 0011 0100
##验证
当接收方接到传过来的比特序列后,如上面的 1011 0011 0100 ,接收方需要验证传过来的数据的正确性,其做法就是用这串比特序列除以 11001(约定的多项式的系数),如果余数为 0 ,则表明数据传输正确。
note:
1.带 r 位的校验码可以检测出长度小于等于 r 个数的突发性错误
2. 为什么数据链路层的CRC校验码总是放在最后面,因为CRC是发送时进行计算,当最后一位数据发送出去,CRC 就立刻附在后面。如果CRC放在前面,则需要先检查全部的帧,在计算,相当于用了两倍的时间。
4.海明码(汉明码)
补充
- 检错码 d 位,需要码距 d+1
- 纠错码 d 位,需要码距 2d+1