CRC校验详解及其在网络编程中的应用

来源:互联网 发布:漫威宇宙 知乎 编辑:程序博客网 时间:2024/06/06 06:56

基本概念

CRC(Cyclic Redundancy Check,循环冗余校验),其实是个很古老的数据校验方法了,记得以前大学<<微机原理>>和<<微机原理与接口技术>>课程都对其进行了介绍,其校验准确度较之普通的奇偶校验、校验和等方法更高,当然计算也略微复杂;较之MD5、SHA1等算法,CRC安全性和准确度方面又略显不足,但计算较之这两者明显简单,效率更高。所以如果仅仅针对网络数据的一致性校验,即收发端数据的是否一致(因为在Socket编程里,单次收到数据的长度和发送数据的长度即使在阻塞模式下,也不一定是相同的,这个依赖于网络环境,虽然TCP协议保证了数据的完整性和一致性,但像这种人为对数据进行了分片的情况,在收到数据时视情况还是有必要进行一下校验),针对这种校验要求,CRC32是明显足够,也不会带来很大的计算负担。

CRC32的C语言实现

关于CRC32(即校验码是32位)实现理论原理,这里不多说,网上有大把的资料,这里主要探究一下怎样用C语言高效的实现CRC32校验算法。
下面的算法用到了查找表的方法,这也是比较常见的以空间换时间的思想。
对于以按字节校验的CRC算法实现中,一个字节8bit,取值范围0~255,每个字节均是如此。因此可以生成一个0~255所有数的校验结果的数组,以后就是取这个数组的值就可以了。
查找表实现代码:

int init_crc32_table(uint32_t crc32_table[]){    uint32_t c;    int i = 0;    int bit = 0;    for (i = 0; i < 256; i++) {        c = (uint32_t)i;        for (bit = 0; bit < 8; bit++) {            if (c & 1) {                c = (c >> 1) ^ (0xEDB88320)//此十六进制数代表CRC32标准多项式;            }            else {                c = c >> 1;            }        }        crc32_table[i] = c;    }    return 0;}

数据校验代码:
uint32_t crc传入的初始值为0xffffffff;

uint32_t make_crc(uint32_t crc, unsigned char *string, uint32_t size, uint32_t crc32_table[]){    while (size--)        crc = (crc >> 8) ^ (crc32_table[(crc ^ *string++) & 0xff]);    return crc;}

后记

上面代码测试过,可以直接用,可以看出,CRC32的实现还是比较容易的,计算效率也不错,如果不是对一致性检测要求过高的话,可以考虑CRC32以及同系的CRC16、CRC8等算法。

1 0