注册 | 登录 忘记密码? 51cto首页 | 博客 | 论坛 | 招聘
热点文章 《网络工程师考试案例动手..
 帮助

对IP首部检验和的理解


2006-08-16 16:56:56
 标签:   [推送到技术圈]

很多文章对ip首部检验和的计算介绍得很简略,在理解上常常会比较困难。这篇文章是我自己的一些理解。或许也有不正确的地方,希望大家指正。
这个问题一直困绕了我很长时间,今天终于理解了。 


我们可以通过spynet sniffer抓包软件,抓取一个ip数据包进行分析研究。
下面我以本机抓到的一个完整的ip首部为例(红色字体表示):

0000: 00 e0 0f 7d 1e ba 00 13 8f 54 3b 70 08 00 45 00
0010: 00 2e be 55 00 00 7a 11 51 ac de b7 7e e3 c0 a8
0020: 12 7a

45 00 00 2e----4表示ip版本号为ip第4版;5表示首部长度为5个32 bit字长,即为20字节;00 2e表示ip总长度为46字节,其中ip数据部分为
26字节。
be 55 00 00----be 55表示标识符;00 00表示3 bit标志及13 bit片偏移量;
7a 11 51 ac----7a表示ttl值为122;11表示协议号为17的udp协议;51 ac表示16 bit首部检验和值;
de b7 7e e3----表示32 bit 源ip地址为222.183.126.227
c0 a8 12 7a----表示32 bit 目的ip地址为192.168.18.122



检验和计算:
首先,把检验和字段置为0。
45 00 00 2e
be 55 00 00
7a 11 00 00<----检验和置为0
de b7 7e e3
c0 a8 12 7a
其次,对整个首部中的每个16 bit进行二进制反码求和,求和值为3ae50,然后3+ae50=ae53(这是根据源代码中算法 cksum = (cksum
>> 16) + (cksum & 0xffff) 进行的 )

最后,ae53+51ac=ffff。因此判断ip首部在传输过程中没有发生任何差错。




    文章评论
 
2006-08-25 16:50:34
不太明白求和具体方法:
我分别用了2进制和16进制的方式算了一下,我的计算过程为分别列出每16位数的反码如4500反码baff,然后统一相加,但是结果不一致,我认为我的计算方式错误,请指教正确的计算方式。

2006-08-25 16:58:45
最近在学习TCP/IP协议,希望能向你学习和探讨有关的内容

2006-08-27 05:45:58
IP 检验和的定义在RFC1071中,可以参考原文来理解
The IP Header Checksum is computed on the header fields only.
Before starting the calculation, the checksum fields (octets 11 and 12)
are made equal to zero.
In the example code,
u16 buff[] is an array containing all octets in the header with octets 11 and 12 equal to zero.
u16 len_ip_header is the length (number of octets) of the header.

2006-08-27 05:47:06
/*
**************************************************************************
Function: ip_sum_calc
Description: Calculate the 16 bit IP sum.
***************************************************************************
*/
typedef unsigned short u16;
typedef unsigned long u32;
u16 ip_sum_calc(u16 len_ip_header, u16 buff[])
{
u16 word16;
u32 sum=0;
u16 i;

2006-08-27 05:47:33
// make 16 bit words out of every two adjacent 8 bit words in the packet
// and add them up
for (i=0;i> 16);
// one's complement the result
sum = ~sum;
return ((u16) sum);
}
"二进制反码求和" 等价于 "二进制求和再取反"
从源代码看,很关键的一点是二进制求出的和如果大于16位时所做的操作,用和值中高16位加上低16位的值作为最终的和值,然后再做取反运算.
我的E_MAIL是 run_compile@yahoo.com.cn ,期待和大家共同交流.

2006-08-27 10:40:51
明白了,多谢!!

2007-11-19 16:44:51
太感谢了,这个问题也是一直困绕了我很长时间

 

发表评论

昵   称:
验证码:  点击图片可刷新验证码  博客过2级,无需填写验证码
内   容: