# IP头部校验和计算

1125156943 贡献于2014-02-10

﻿unsigned short checksum(unsigned short *buf, int nword) { unsigned long sum; for(sum = 0; nword > 0; nword--) sum += *buf++; sum = (sum>>16) + (sum&0xffff); sum += (sum>>16); return -sum; } 让我们假设一个IP头数据，来解cksum的惑 IP头数据: 01000101 /*ver_hlen*/ 00000000 /*tos*/ 00000000 00000010 /*len*/ 00000000 00000000 /*id*/ 00000000 00000000 /*offset*/ 00000100 /*ttl*/ 00010001 /*type*/ 00000000 00000000 /*cksum(0)*/ 01111111 00000000 00000000 00000001 /*sip*/ 01111111 00000000 00000000 00000001 /*dip*/ (1)16比特分组； (2)校验和清‘0’ (3)求所有16比特之和 01000101 00000000 /*ver_hlen*/ 00000000 00000010 /*len*/ --------------------- 01000101 00000010 00000000 00000000 /*id*/ --------------------- 01000101 00000010 00000000 00000000 /*offset*/ --------------------- 01000101 00000010 00000100 00010001 /*ttl*//*type*/ --------------------- 01001001 00010011 00000000 00000000 /*cksum(0)*/ --------------------- 01001001 00010011 01111111 00000000 /*sip*/ --------------------- 11001000 00010011 00000000 00000001 /*sip*/ --------------------- 11001000 00010100 01111111 00000000 /*dip*/ --------------------- 101000111 00010100 00000000 00000001 /*dip*/ --------------------- 101000111 00010101 sum (4)把求得的和模（216-1） 00000000 00000001 (sum>>16) 01000111 00010101 (sum&0xffff) --------------------- 01000111 00010110 (5)在(4)的基础上求二进制反码 10111000 11101001 cksum 说白了就是循环加，然后在取反! 对方机器调用checksum()计算校验和，如果校验和为0表明IP包传输正确 ----------------------------------------------------------- 01000101 /*ver_hlen*/ 00000000 /*tos*/ 00000000 00000010 /*len*/ 00000000 00000000 /*id*/ 00000000 00000000 /*offset*/ 00000100 /*ttl*/ 00010001 /*type*/ 10111000 11101001 /*cksum(0)*/ 01111111 00000000 00000000 00000001 /*sip*/ 01111111 00000000 00000000 00000001 /*dip*/ 01000101 00000000 00000000 00000010 --------------------- 01000101 00000010 00000000 00000000 --------------------- 01000101 00000010 00000000 00000000 --------------------- 01000101 00000010 00000100 00010001 --------------------- 01001001 00010011 10111000 11101001 --------------------- 100000001 11111100 01111111 00000000 --------------------- 110000000 11111100 00000000 00000001 --------------------- 110000000 11111101 01111111 00000000 --------------------- 111111111 11111101 00000000 00000001 --------------------- 111111111 11111110 sum 00000000 00000001 (sum>>16) 11111111 11111110 (sum&0xffff) ---------------------- 11111111 11111111 ~sum 00000000 00000000 现在我们所用的机器设备大多数是使用二进制补码算法进行计算的