1、1的补码用在TCP、IP的校验和中,而平时学习的补码时 2 的补码,即整数的补码和原码相同,负数的补码按位取反加 1(符号位不变)。
2、1的补码:是一个对称的系统,即一个数和其相反数(1的补码)相加结果一定为 0。0分为正 0和负 0,校验和的计算原理就是基于此,即待发送数据的 1 的补码表示法和其相反数 1 的补码相加结果一定为 0,例如0111111111111111(+32767)按位取反即得到1000000000000000(-32767),于是二者相加的结果为1111111111111111(-0)。
3、IP 校验和算法:
IP 校验算法将待发送的数据按 16bit(0xffff)进行累加,若产生进位,则对进位 位继续累加直到无进位为止,最后将产生的累加和按位取反,得到待发送数据的校验和,并且校验和的值连同待发送数据一起发送给数据接收方。接收方在收到数据后,按 16 bit依次累加收到的数据,若累加结果为 -0,表示数据传输过程中没有发生错误,否则认为数据有错,丢弃该数据。
4、举例:
序列:08 00 04 00 14 00 61 62 63 64(16进制)
1.对此序列按16bit累加:
08 00
04 00
14 00
61 62
+ 63 64
----------------
E4 C6
2.对累加结果按位取反:0x1B39
3.E4 C6 + 1B 39 = FF FF
5、程序:
/* 校验和 */
u16 checksum(u8 *buf/*待发送数据的缓存指针*/, int len/*待发送数据的长度*/)
{
u32 sum=0;
u16 *cbuf;
cbuf=(u16 *)buf;/*16 比特位计算*/
while(len > 1){
sum += *cbuf++;
len-=2; /*剩余未累加的16bit的个数*/
}
/* 当len为奇数时用最后一个字节进行补齐 */
if(len)
sum+=*(u8 *)cbuf;/*用最后 1 个字节补齐*/
//判断是否有 16 bit加法溢出,若有则将进位位继续累加直到无进位
sum=(sum>>16)+(sum & 0xffff);
sum+=(sum>>16);
/*
while(sum >> 16)
sum=(sum>>16)+(sum & 0xffff);
*/
return ~sum;
}