网络数据包效验和(checksum)的计算

王朝other·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

在网络传送的数据包为了保证传送正确都含有效验字段,IP、arp、tcp等每

个数据段都有自己的效验和。

效验的计算并不复杂。把相应数据包段的所有数据看成一个字节数组

{a,b,c,d,e},把他们分成16bit一组

{[ab],[cd],[e0]}

计算其和:

[ab]

[cd]

[e0]

--------

[xy]

计算采用循环进位,最高位的进位加到最低位,

如果计算出的[xy]所有位都为1(即为1111 1111)则效验通过。

如果[cd]为效验和的话,已经填好其他各个字节,如何计算出[cd]

(checksum)的值呢?我们首先用0填充[cd],然后算出[xy],则正确的[cd]应该为计

算出的[xy]按位求反的结果。这样才能保证整个数据包段通过效验。

实际程序中,因为现在的机器都是32位的,所以采用变通的算法:

Byte-by-byte "Normal" Swapped

Order Order

Byte 0/1: 00 01 0001 0100

Byte 2/3: f2 03 f203 03f2

Byte 4/5: f4 f5 f4f5 f5f4

Byte 6/7: f6 f7 f6f7 f7f6

--- --- ----- -----

Sum1: 2dc 1f0 2ddf0 1f2dc

dc f0 ddf0 f2dc

Carrys: 1 2 2 1

-- -- ---- ----

Sum2: dd f2 ddf2 f2dd

Final Swap: dd f2 ddf2 ddf2

------------------------------

Byte 0/1/2/3: 0001f203 010003f2 03f20100

Byte 4/5/6/7: f4f5f6f7 f5f4f7f6 f7f6f5f4

-------- -------- --------

Sum1: 0f4f7e8fa 0f6f4fbe8 0fbe8f6f4

Carries: 0 0 0

Top half: f4f7 f6f4 fbe8

Bottom half: e8fa fbe8 f6f4

----- ----- -----

Sum2: 1ddf1 1f2dc 1f2dc

ddf1 f2dc f2dc

Carrys: 1 1 1

---- ---- ----

Sum3: ddf2 f2dd f2dd

Final Swap: ddf2 ddf2 ddf2

可以看到先求32位的checksum,然后将高8位与低八位相加,最终求出的

checksum是相同的。

给出一段C++实现的算法:

in 6

{

/* Compute Internet Checksum for "count" bytes

* beginning at location "addr".

*/

register long sum = 0;

while( count > 1 ) {

/* This is the inner loop */

sum += * (unsigned short) addr++;

count -= 2;

}

/* Add left-over byte, if any */

if( count > 0 )

sum += * (unsigned char *) addr;

/* Fold 32-bit sum to 16 bits */

while (sum>>16)

sum = (sum & 0xffff) + (sum >> 16);

checksum = ~sum;

}

参考文献:RFC1071 网址:http://www.faqs.org/rfcs/rfc1071.html

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
 
 
© 2005- 王朝網路 版權所有 導航