1. 程式人生 > 其它 >課題需要 --> 如何計算校驗和?

課題需要 --> 如何計算校驗和?

想要修改一個pcap包,除了對於提取後的每個特徵進行修改以外,想要保證資料包的功能,能夠重傳,還要保證包頭的校驗和是計算正確的,這就需要按照資料包的具體內容對於包頭校驗和進行更改。

那麼,都有哪些包頭需要計算校驗和,校驗和又覆蓋了哪些內容呢? 首先給出一個總結:

IP、ICMP、UDP和TCP報文頭都有檢驗和欄位,大小都是16bit。

(1)IP校驗和:IP首部。

(2)ICMP校驗和:ICMP首部+ICMP資料;

(3)UDP、TCP校驗和:首部+資料+12個位元組偽首部(源IP地址、目的IP地址、協議、TCP/UDP包長)。

傳送資料包的一端會首先根據內容,計算校驗和並填充資料包頭,這裡上述3種校驗和的計算方法是基本一致的,包括:

(1)把校驗和欄位設定為0。

(2)把需要校驗的資料看成以16位為單位的數字組成,依次進行二進位制反碼求和。

(3)把得到的結果存入校驗和欄位中。

而上述計算方法對於不同資料包包頭的作用範圍也不同,區別在於:

(1)IP校驗和:只校驗20位元組的IP報頭。

(2)ICMP校驗和:覆蓋整個報文(ICMP報頭+ICMP資料)。

(3)UDP和TCP校驗和:不僅覆蓋整個報文,而且還有12個位元組的IP偽首部,包括源IP地址(4位元組)、目的IP地址(4位元組)、協議(2位元組)、TCP/UDP包長(2位元組)。

  另外,需要注意的是,UDP、TCP資料報的長度可以為奇數字節。因為計算時是16位為單位,此時計算校驗和時需要在最後增加一個填充位元組0(只用於計算校驗和,不傳送出去)。而在UDP傳輸協議中,校驗和是可選的,當校驗和欄位為0時,表明該UDP報文未使用校驗和,接收方就不需要校驗和檢查了。那如果UDP校驗和的計算結果是0時怎麼辦?這裡給出答案,如果校驗和的計算結果為0,則存入的值為全1(65535),這在二進位制反碼計算中是等效的。

接收資料包的一端,則會根據收到的實際內容,與傳送端給出的校驗和作比較,進行校驗,其步驟為:

(1)把首部看成以16位為單位的數字組成,依次進行二進位制反碼求和,包括校驗和欄位;

(2)檢查計算出的校驗和的結果是否為0;

(3)如果等於0,說明被整除,校驗和正確。否則,校驗和就是錯誤的,協議棧要拋棄這個資料包。

  

這裡給出二進位制反碼求和操作的原理:

(1)二進位制反碼求和,就是先把兩個數取反,然後求和,如果最高位有進位,則向低位進1。

(2)另外,先取反後相加與先相加後取反,得到的結果是一樣的。因此,通常實現程式碼都是先相加,最後再取反。

【一個例子】二進位制反碼求和

  對一個無符號的數,先求其反碼,然後從低位到高位,按位相加,有溢位則向高位進1(和一般的二進位制法則一樣),若最高位有進位,則向最低位進1

  這裡的反碼和有符號反碼不同,不分正負,直接按位取反。此外,進位方式也與我們學習的加法法則不同,最高位有進位,需要向最低位進1。為什麼要這樣呢?

  對此分析一下,上面的這種操作,使得在傳送加法進位溢位時,溢位值並不是10000,而是1111,也就是當相加結果滿1111時溢位,這樣也可以說明為什麼0000和1111都表示0了。

下面是兩種二進位制反碼求和的運算:

原碼加法運算:3(0011)+5(0101)=8(1000)

8(1000)+9(1001)=1(0001)

反碼加法運算:3(1100)+5(1010)=8(0111)

8(0111)+9(0110)=2(1101)

從上面的例子中,當加法未發生溢位時,原碼與反碼加法運算結果一樣;當有溢位時,結果就不一樣了,原碼是滿10000溢位,而反碼是滿1111溢位,所以相差正好是1。

此外,還有需要清楚的問題,為什麼我們使用的是反碼和,而不是直接求和呢?或者是補碼和【在計算機裡面資料是以補碼的形式存在】呢?

這裡給出學習過程中瞭解到的,在TCP/IP校驗和中使用反碼求和的一些優點:

(1)不依賴系統是大端小端。即無論你是傳送方計算機或者接收方檢查校驗和時,都不要呼叫htons或者ntohs,直接通過演算法就可以得到正確的結果。用反碼求和時,交換16位數的位元組順序,得到的結果相同,只是位元組順序相應地也交換了;而如果使用原碼或者補碼求和,得到的結果可能就不同。

(2)計算和驗證校驗和比較簡單、快速。

To see I can not see, to know I do not know.