为建立中文知识库加块砖 ——中科大胡不归
0. 前言
如果必须加入一种方法来校验协议数据,累加校验不失为一种好的方案。MD5计算出的Hash太长了,校验和不过1或2个字节,当然MD5的安全性也不是校验和能比的。
1. 校验和原理
1.1 发送方生成检验和
1.将发送的进行检验和运算的数据分成若干个16位的位串,每个位串看成一个二进制数,这里并不管字符串代表什么,是整数、浮点数还是位图都无所谓。
2.将IP、UDP或TCP的PDU首部中的检验和字段置为0,该字段也参与检验和运算。
3.对这些16位的二进制数进行1的补码和(one's complement sum)运算,累加的结果再取反码即生成了检验码。将检验码放入检验和字段中。
其中1的补码和运算,即带循环进位(end round carry)的加法,最高位有进位应循环进到最低位。反码即二进制各位取反,如0111的反码为1000。
1.2 接收方校验检验和
1.接收方将接收的数据(包括检验和字段)按发送方的同样的方法进行1的补码 和运算,累加的结果再取反码。
2.校验,如果上步的结果为0,表示传输正确;否则,说明传输有差错。
1.3 算法图示
2. 代码实现
2.1 生成检验和
public static byte[] GetCheckSum(byte[] data)
{
List<byte> m = new List<byte>();
int sum = 0;
for (int i = 0; i < data.Length; i++)
{
m.Add(data[i]);
sum += data[i];
}
sum = sum % 256;
sum = ~sum + 1;
m.Add((byte) sum);
return m.ToArray();
}
返回值是追加了校验和的原始字节数组。
2.2 接收方校验
public static byte DoSumCheck(byte[] data)
{
byte cs = 0;
for (int i = 0; i < data.Length; i++)
{
cs = (byte)((cs + data[i]) % 256);
}
return cs;
}
DoSumCheck的参数就是原字节数组在尾部加上了校验和,如果数据正确运算结果就为00。
3. 效果展示
调用演示:
运行结果: