循环冗余校验(Cyclic Redundancy Check,简写CRC),是一种常用的、检错能力相当强的校验算法。
本文不详细介绍CRC算法的理论,直接给出计算结果为2个字节的计算流程及实现代码。
计算流程
- 定义一个16位无符号类型的变量,并初始化为0xFFFF,称之为CRC变量;
- 把数据包中的第一个字节与CRC变量中的低字节进行异或运算,结果存回CRC变量;
- 将CRC变量向右移一位,最高位填以0,最低位移出并检测;
- 如果最低位为0:重复第3步(进行下一次移位);如果最低位为1:将CRC变量与固定值0xA001进行异或运算;
- 重复第3步和第4步直到8次移位,这样就完成了对数据包中第一个字节的处理;
- 重复第2步到第5步来处理数据包中的下一个字节,直到数据包中所有的字节都处理完;
- 最终CRC变量的值就是CRC的值。
用C语言实现
/* 代码片段,摘自:plat_lib.c */
测试代码:
/* 代码片段,摘自:test.c */
Makefile
TARGET = test
SOURCE := $(wildcard *.c) $(wildcard *.cpp)
OBJS := $(patsubst %.c,%.o,$(patsubst %.cpp,%.o,$(SOURCE)))
$(TARGET): $(OBJS)
gcc -o $@ $(OBJS)
clean:
rm -rf *.o $(TARGET)
测试结果
// 编译
[root@localhost checksum]# make
cc -c -o protocol.o protocol.c
cc -c -o plat_lib.o plat_lib.c
cc -c -o plat_log.o plat_log.c
cc -c -o test.o test.c
gcc -o test protocol.o plat_lib.o plat_log.o test.o
// 运行测试程序
[root@localhost checksum]# ./test
crc1 = BB2A, crc2 = 877A
优缺点
CRC算法比校验和算法复杂,计算过程会占用较多的计算机资源(比如CPU资源),其优点是检错能力强,举例说明如下,有2份元数据,如下:
虽然只是有2个字节的数据交换了一下位置,但得到了不同的CRC校验码,这是校验和算法或一些其他简单算法做不到的。
补充:
通信协议中,CRC校验码通常按如下方式使用:CRC校验码由发送方计算出来,然后附加到数据包中,接收方在接收数据时以同样的算法重新计算CRC值,然后与接收到的CRC校验码进行比较,如果这两个值不相等,就说明数据传输过程中出现了错误,数据不可靠,直接丢弃不做处理。