1、IP 首部校验和的计算方法:1.把校验和字段清零。2.然后对每 16 位(2 字节) 进行二进制反码求和,反码求和的意思是先对每 16 位求和,再将得到的和转为反码。接下来详细描述反码求和的步骤 :看下面的代码算法:SHORT checksum(USHORT* buffer, int size)unsigned long cksum = 0;while(size1)cksum += *buffer+;size -= sizeof(USHORT);if(size)cksum += *(UCHAR*)buffer;cksum = (cksum16) + (cksum cksum += (cksum
2、16); return (USHORT)(cksum);参数 buffer 是指向 16 位整数的指针,刚开始指向的是 IP 首部的起始地址,参数 size 是IP 首部的大小。while 循环是将 IP 首部的内容以 16 位为单元加在一起,如果没有整除(即size 还有余下的不足 16 位的部分) ,则加上余下的部分,此时的 cksum 就是相加后的结果,这个结果往往超出了 16 位,因为校验和是 16 位的,所以要将高 16 位和计算得到的cksum 再加工。再加工第一步:cksum = (cksum16) + (cksum sum16 是将高 16 位移位到低16 位,sum 第一步相
3、加时很可能会产生进位,因此要再次把进位移到低 16 位进行相加。 这样就加工好了,接下来就是取反,并强制转换为 16 位,这样就得到了最终的校验和。校验和计算出来了,接下来就是该如何校验 :接收方进行校验时,也是对每 16 位进行二进制反码求和。接收方计算校验和时的首部与发送方计算校验和时的首部相比,多了一个发送方计算出来的校验和。因此,如果首部在传输过程中没有发生差错,那么接收方计算的结果应该为全一,因为接收方计算除校验和以外的部分得到值是校验和的反码,再加多出来的校验和当然是全一了。最后对上述过程举个例子:IP 头:45 00 00 3189 F5 00 006E 06 00 00(校验字
4、段)DE B7 45 5D - 222.183.69.93C0 A8 00 DC - 192.168.0.220计算: 4500 + 0031 +89F5 + 0000 + 6e06+ 0000 + DEB7 + 455D + C0A8 + 00DC =3 22C40003 + 22C4 = 22C722C7 = DD38 -即为应填充的校验和当接受到 IP 数据包时,要检查 IP 头是否正确,则对 IP 头进行检验,方法同上:计算:4500 + 0031 +89F5 + 0000 + 6E06+ DD38 + DEB7 + 455D + C0A8 + 00DC =3 FFFC0003 + FFFC = FFFF得到的结果是全一,正确。