解
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協議在網路中當然非常重要了,...