TCP頭校驗和計算演算法詳解

2021-06-06 05:42:24 字數 3665 閱讀 3891

當傳送ip包時,需要計算ip報頭的校驗和:

1、  把校驗和字段置為0;

2、  對ip頭部中的每16bit進行二進位制求和;

3、  如果和的高16bit不為0,則將和的高16bit和低16bit反覆相加,直到和的高16bit為0,從而獲得乙個16bit的值;

4、  將該16bit的值取反,存入校驗和字段。

◆當接收ip包時,需要對報頭進行確認,檢查ip頭是否有誤,演算法同上2、3步,然後判斷取反的結果是否為0,是則正確,否則有錯。

演算法:short checksum(ushort* buffer, int size)

if(size)

cksum = (cksum>>16) + (cksum&0xffff);  //將高16bit與低16bit相加

cksum += (cksum>>16);             //將進製到高位的16bit與低16bit 再相加

return (ushort)(~cksum);

}例項:

ip頭:  

45 00    00 31

89 f5    00 00

6e 06    00 00(校驗字段)

de b7   45 5d       ->    222.183.69.93

c0 a8   00 dc     ->    192.168.0.220

計算:   

4500 + 0031 +89f5 + 0000 + 6e06+ 0000 + deb7 + 455d + c0a8 + 00dc =3 22c4

0003 + 22c4 = 22c7

~22c7 = dd38      ->即為應填充的校驗和

當接受到ip資料報時,要檢查ip頭是否正確,則對ip頭進行檢驗,方法同上:

計算:4500 + 0031 +89f5 + 0000 + 6e06+ dd38 + deb7 + 455d + c0a8 + 00dc =3 fffc

0003 + fffc = ffff

~ffff = 00000     ->正確

tcp首部檢驗和與ip首部校驗和的計算方法相同,在程式中使用同乙個函式來計算。

需要注意的是,由於tcp首部中不包含源位址與目標位址等資訊,為了保證tcp校驗的有效性,在進行tcp校驗和的計算時,需要增加乙個tcp偽首部的校驗和,定義如下:

struct 

psd_header;

然後我們將這兩個字段複製到同乙個緩衝區sendbuf中並計算tcp校驗和:

memcpy(sendbuf,&psd_header,sizeof(psd_header)); 

memcpy(sendbuf+sizeof(psd_header),&tcp_header,sizeof(tcp_header));

tcp_header.th_sum=checksum((ushort *)sendbuf,sizeof(psd_header)+sizeof(tcp_header));

====

--------

網路資料報效驗和(checksum)的計算

在網路傳送的資料報為了保證傳送正確都含有效驗字段,ip、arp、tcp等每

個資料段都有自己的效驗和。

效驗的計算並不複雜。把相應資料報段的所有資料看成乙個位元組陣列

,把他們分成16bit一組

計算其和:

[ab]

[cd]

[e0]

--------

[xy]

計算採用迴圈進製,最高位的進製加到最低位,

如果計算出的[xy]所有位都為1(即為1111 1111)則效驗通過。

如果[cd]為效驗和的話,已經填好其他各個位元組,如何計算出[cd]

(checksum)的值呢?我們首先用0填充[cd],然後算出[xy],則正確的[cd]應該為計

算出的[xy]按位求反的結果。這樣才能保證整個資料報段通過效驗。

實際程式中,因為現在的機器都是32位的,所以採用變通的演算法:

byte-by-byte 

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

/*  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;

}====

TCP頭校驗和計算演算法詳解

我就不管是按 位 bit 取反相加,還是 按 1的補碼 相加了,總之 就是把需要進行校驗的 字串 加 起來,把這相加的 結果取反當做 校驗和 checksum 比如,相加的結果是0101,那麼 校驗和 就 是1010,驗證的時候呢,就是0101 1010 1111,取反後,就是0 如果驗證得 零 0...

C 計算ICMP頭的校驗和例項

複製 如下 ushort checksum ushort buff,int nsize 程式設計客棧 如果為奇數,將最後乙個字擴充套件到雙字,再累加 www.cppcns.comnbsp if nsize nbs 將cksum的高16位與低16位相加,取反後得到校驗和 cksum cksum 16 ...

IP和TCP包頭校驗和計算方法

出處 校驗和的演算法 將資料以字為單位累加到乙個雙字中,如果資料長度為奇數,最後乙個位元組要先變成字,然後在加到原來的雙字中,最後得到的結果是乙個雙字,最後將這個雙字的高16位和低16位反覆相加,直到高16位為0,從而就獲得乙個16位的值,再將這個16位的值取反就得到校驗和的值了。在接收端接收到ip...