redis-CRC16
CRC16
当数据帧长度在8bits-128bits范围内时,推荐CRC-8(CRC-8能够减少额外比特的开销,且有更好的性能表现)
当数据帧长度在128bits-2048bits范围内时,推荐CRC-12,CRC-16,CRC-CCITT(CRC-12额外比特的开销更小,且用于6bit字符流的传输;对于16bits的标准,更推荐美国标准CRC-16,性能略优于CRC-CCITT);
当因数据帧长度更长、信道不稳定等情况而需要更高的性能时,CRC-32、CRC-32C将是更好的选择;
Redis-基于字节查表法的CRC校验码生成算法
CRC16的校验码是两个字节,所以Redis的源码中使用了 uint16_t类型(unsigned short int)
CRC16要校验的数据位是8位
在求解CRC校验码的过程中,会用到模二除,实际我们最后不关心它的商Q(x),只关心关心余数R(x),它也是两个字节的大小
余数R(x)分为高字节RH(x)和低字节RL(x)两个部分:R(x) = RH(x) * X^8 + RL(x) (这个+,可以理解成异或,也可以理解成+号)
任何数和0异或结果还是这个数
流程
- CRC-16码由两个字节构成,在开始时CRC寄存器的每一位都预置为1
- 然后把CRC寄存器与8-bit的数据进行异或
- 之后对CRC寄存器从高到低进行移位,在最高位(MSB)的位置补零,而最低位(LSB,移位后已经被移出CRC寄存器)如果为1,则把寄存器与预定义的多项式码进行异或,否则如果LSB为零,则无需进行异或。
- 重复上述的由高至低的移位8次,第一个8-bit数据处理完毕
- 用此时CRC寄存器的值与下一个8-bit数据异或并进行如前一个数据似的8次移位。
- 所有的字符处理完成后CRC寄存器内的值即为最终的CRC值。
Redis使用的是CRC-16-CCITT标准,即G(x)为:x^16 + x^12 + x^5 + 1 。
G(x)的通常表征方式是将多项式转换成二进制: 1 0001 0000 0010 0001。用十六进制表示为:0x11021。