几行代码实现CRC循环冗余检验

简介: 几行代码实现CRC循环冗余检验

一.认识CRC循环冗余检验

CRC(Cyclic Redundancy Check)是一种循环冗余检验,用于验证数据在传输过程中是否发生了错误。它通过对数据进行一系列数学运算并生成一个校验码来实现这一目的。


CRC算法通常使用二进制多项式进行计算。将要发送的数据视为一个二进制多项式,然后通过除以另一个预定义的二进制多项式得到余数。这个余数就是CRC校验码,可以随原始数据一起发送给接收方。接收方也会对接收到的数据进行相同的计算,并比较计算出来的CRC码与发送方发送的CRC码是否相等,如果不相等,则说明数据在传输过程中发生了错误。


CRC是一种高效、简单和广泛使用的错误检测方法,常用于计算机网络、通信系统、存储系统等领域。同时这也是考研的重要考点,你值得拥有。


二. 算法原理

CRC循环冗余检验,其原理可以简单描述为:在发送方通过生成CRC校验码并将其添加到待发送数据后一起发送给接收方,在接收方通过计算CRC校验码来检测数据是否有误。如果计算得到的CRC校验码与接收方接收到的CRC校验码不同,则说明数据传输过程中发生了错误。

(如果你实在不理解它的原理,会笔算和代码实现就行了。)

直接上操作步骤:


确定生成多项式G(Generator Polynomial),一般会选择一个固定的标准多项式,如CCITT、CRC-16、CRC-32等。


将待发送的数据D按照指定的位数k进行分组,并将每个分组看成二进制数,首位为最高位。


在D的右侧追加k-1个0,构成长度为n的新数R。


用R去除G,得到商Q和余数C,将C作为CRC校验码添加到D的右侧。


接收方收到数据后,重复第2步至第3步,然后用接收到的校验码对R进行除法运算,若余数为0则说明接收到的数据未出错;否则表明接收到的数据存在差错。


三.CRC的优缺点

1. 优点

高效性:CRC可以在接收方快速地检测出传输过程中是否发生了误码,因为其采用了多项式求余的方式,只需要对数据进行简单的异或和操作即可得到校验码,运算速度快。


高准确性:CRC能够检测出大部分的错误比如单比特差错、双比特差错等,而且在实践中被证明效果稳定可靠。


灵活性:CRC可以应用于各种不同的数据通信协议和数据格式之间的传输,具有较好的通用性。


2.缺点

无法纠正错误:与纠错码不同,CRC只能检测出传输过程中的错误,而不能进行纠正,需要重新发送数据。


易受攻击:由于CRC算法的特性,一些恶意攻击者可以通过改变数据中的某些位来产生相同的CRC校验码,从而骗过接收方,这就会导致信息的安全性问题。


传输距离受限:CRC算法的可靠性和正确性受传输距离的影响,如果传输过程中距离太远,则容易发生误码。


四.笔算

要写代码实现,你首先的学会笔算,下面我直接用我之前网上学习的一个例子带你学会笔算。

d92f17f7c6f1309b8cf289e45bc49c48.jpg

按照我上面的批注来,你就完成了CRC的发送部分。

在本例中,最终的发送数据时 10110011010,假设接收端接收的数据恰好也是 10110011010,接收端只需要将接收的数据与除数也就是 g(x) 进行异或运算,最后结果发现是0,表示接收正确。但如果接收端接收的数据不是 10110011010 ,那么异或运算时的结果就不为0,那么接收端就明白传输错误。


五.python代码实现

代码比较基础,有一定python基础的人一定会看懂。

这里重点指出一个函数:bin()。

由于 bin 函数讲解很多,这里不讲解,大家可以去 ( bin函数讲解)学习。

def crc(str1: str, str2: str) -> dict:
    """自定义CRC计算校验码"""
    # str1附加len(str2)-1个0
    str = str1 + '0' * (len(str2) - 1)
    # 循环异或
    while len(str) >= len(str2):
        # 计算机进行模2运算,默认右对齐,而这里进行异或需要左对齐
        # 确保异或前左对齐(无前缀0),每次计算str需要左移多少位
        length = len(str) - len(str2)
        temp = int(str, 2) ^ (int(str2, 2) << length)
        # 每次异或结果str转二进制字符串(自动去除前缀0b)
        # bin函数的结构为一个以‘0b’开始的字符串,我们进行切割,只需要后面的数值即可
        str = bin(temp)[2:]
    # 补全校验码的有效位数为k-1
    k = len(str2)
    crc_len = k - 1
    crc_str = str.zfill(crc_len)
    # 返回一个字典,包含计算出来的校验码和发送的数据
    result = {'a': crc_str, 'b': str1 + crc_str}
    return result
l1 = crc('101011001', '11001')
print(f"校验码:{l1['a']},发送的数据是{l1['b']}")
print('----------------------')
l2 = crc('1011001', '11001')
print(f"校验码:{l2['a']},发送的数据是{l2['b']}")

这里代码的实现,我原来也是用了几十行代码,后来学习了别人的思路,才简化成几行,去掉注释你发现也就几行代码实现了 CRC 循环冗余检验的功能。

运行结果可以和你的笔算结果进行对比。


六.实验结果


b156b2ceba4e0524c2a161e4564098fd.jpg

相关文章
|
6月前
|
数据安全/隐私保护 C++ Python
Base32系列编码 代码实现过程
Base32系列编码 代码实现过程
71 0
|
6月前
CRC循环冗余码计算
CRC循环冗余码计算
59 0
|
6月前
|
算法
模二运算、循环冗余检验(CRC)
模二运算、循环冗余检验(CRC)
98 0
|
算法
CRC 校验算法
CRC 校验算法
214 0
|
存储 PHP
|
算法 C语言 索引