IP協議的CheckSum函式之理解

2021-04-02 20:29:45 字數 4593 閱讀 3621

ip協議中的

checksum

author:zfive5(zhaozidong)

email :[email protected]

最近一段時間,對網路又開始追根溯源,最好的辦法就是開啟開源協議棧看乙個究竟,不求寫乙個完整的

ip協議棧,但求通達解惑!

眾所周知,

ip頭定義如下:

struct

ipheader;

ip頭中的大多欄位都好理解

,只要一本

tcp/ip

入門的書就可以明明白白了,對

cksum

字段理解,如果只是看書,到頭來很可能還不清楚怎麼算它!

關於

cksum_header

的描述在《

tcp/ip

卷一》中是這樣描述的: 「

首部檢驗和字段是根據

i p首部計算的檢驗和碼。它不對首部後面的資料進行計算。

i c m p

、i g m p

、u d p

和t c p

在它們各自的首部中均含有同時覆蓋首部和資料檢驗和碼。

為了計算乙份資料報的

i p檢驗和,首先把檢驗和字段置為

0。然後,對首部中每個

16 bit

進行二進位制反碼求和(整個首部看成是由一串

16 bit

的字組成),結果存在檢驗和字段中。當收到乙份

i p資料報後,同樣對首部中每個

16 bit

進行二進位制反碼的求和。由於接收方在計算過,程中包含了傳送方存在首部中的檢驗和,因此,如果首部在傳輸過程中沒有發生任何差錯,那麼接收方計算的結果應該為全

1。如果結果不是全

1(即檢驗和錯誤),那麼

i p就丟棄收到的資料報。但是不生成差錯報文,由上層去發現丟失的資料報並進行重傳。

不知道有多少能人看完此描述後,寫出演算法或函式來!

正確的函式如下:

unsigned shortchecksum(unsigned short *szbuf,int

isize)

讓我們假設乙個

ip頭資料,來解

cksum

的惑!

ip頭資料:

01000101/*

ver_hlen;*

/00000000/*

tos*/

00000000 00000010/*

len*/

00000000 00000000/*

id*/

00000000 00000000/*

offset*/

00000001/*

ttl*/

00010001/*

type*/

00000000 00000000/*

cksum(0

)*/

01111111 00000000 00000000 0000001/*

sip*/

01111111 00000000 00000000 0000001/*

dip*/

運算過程(注意是大端格式加):

01000101 00000000

01000101 00000000

00000000 00000010

01000101 00000010

00000000 00000000

01000101 00000010

00000000 00000000

01000101 00000010

00000100 00010001

01001001 00010011

00000000 00000000

01001001 00010011

01111111 00000000

11001000 00010011

00000000 00000001

11001000 00010100

01111111 00000000

101000111 00010100

00000000 00000001

和: 101000111 00010101

cksum

=(cksum>>16)+(cksum&0xffff)後:

00000000 000000011

01000111 00010101

和: 01000111 00010110

cksum

+=(cksum>>16)後:

01000111 00010110

00000000 00000000

和: 01000111 00010110

~: 10111000 11101000(效檢和)

運算過程(注意用小端格式加):

00000000 01000101

00000000 01000101

00000010 00000000

00000010 01000101

00000000 00000000

00000010 01000101

00000000 00000000

00000010 01000101

00010001 00000100

00010011 01001001

00000000 00000000  

00010011 01001001

00000000 01111111  

00010011

11001000

00000001 00000000  

00010100 11001000

00000000 01111111  

00010101 01000111

00000001 00000000  

和: 00010110 01000111

cksum

=(cksum>>16)+(cksum&0xffff)後:

00000000 000000001

00010110 01000111

和: 00010110 01000111

cksum

+=(cksum>>16)後:

00010110 01000111

00000000 00000000

和: 00010110 01000111

~: 11101001 10111000(效檢和)

checksum2

11101000 10111000(小端)

checksum1

10111000 11101000(大端)

演算法一樣,說白了就是迴圈加,加到沒有進製為止,然後在取反!

在現在《

tcp/

ip卷二》中的

cksum

實現有以下語句:

while(sum>>16)

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

通過它更能說明就是在作迴圈加操作,現在又有乙個疑問:

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

cksum+=(cksum>>16);

while(sum>>16)

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

等價嗎?

等價,在一定條件下

等價,大家都知道

ip理論上最長是

0xffff

那麼

checksum

最大不會超過:

0xffff0000

這樣

>>16

後為0xffff

0xffff+checksum

最大0x1fffe,

0x1fffe >>16+0x1fffe=0xffff

注意了沒有了進製

所以得到等價的結論!

以前每讀到

cksum

註解時,書上只是草草曰16位反碼和之云云,沒有強調進製也要參加運算一點徵兆,直到最近寫了不少程式才看清楚這個細節!

原始碼之下必解惑!

IP協議的CheckSum函式之理解

解ip協議中的checksum author zfive5 zhaozidong email zfive5 yahoo.com.cn 最近一段時間,對網路又開始追根溯源,最好的辦法就是開啟開源協議棧看乙個究竟,不求寫乙個完整的ip協議棧,但求通達解惑!眾所周知,ip頭定義如下 struct iphe...

詳解IP首部效檢和 checksum

最近一段時間,對網路又開始追根溯源,最好的辦法就是開啟開源協議棧看乙個究竟,不求寫乙個完整的ip協議棧,但求通達解惑!眾所周知,ip頭定義如下 struct ipheader unsigned char ver hlen unsigned char tos unsigned short len un...

TCP IP協議 IP協議

ip協議層 在傳輸層的下邊,鏈路層的上邊。ip層封裝後稱為資料報 傳輸層叫資料段,鏈路層叫資料幀。值得注意的是,不是所有的乙太網資料幀都是ip資料報,至少乙太網還要使用arp協議。不是所有的ip資料報都是udp或tcp資料,因為比如icmp igmp也用ip傳送資料 ip協議在網路中當然非常重要了,...