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 su m 00000000 00000001 (sum>>16) 11111111 11111110 (sum&0xffff) ---------------------- 11111111 11111111 ~sum 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 现 在 我 们 所 用 的 机 器 设 备 大 多 数 是 使 用 二进制补码算法进行计算的