天天看點

計算IP首部檢驗和

以前在學謝希仁教授主編的《計算機網絡》時,一直沒弄懂IP首部的校驗和是如何計算的。今天在看《TCP/IP詳解 卷一》時,看到了一段關于首部校驗和的描述。如下:

為了計算一份資料報的IP校驗和,首先把檢驗和的字段設定為0。然後,對首部中每個16bit進行二進制反碼求和(整個首部看成是由一串16bit的字組成),結果存在校驗和字段中。當收到一份IP資料報後,同樣對首部中每16bit進行二進制反碼求和。由于接收方在計算過程中包含了發送方存在首部中的檢驗和,是以,如果首部在傳輸過程中沒有發生任何差錯,那麼接收方計算的結果應該全為1。如果結果不是全1,即檢驗和錯誤。

通過Wireshark抓到一個IP資料包如下,

計算IP首部檢驗和

也就是說IP資料包未發送時的頭部為:

head = [0x45c0, 0x0028, 
        0x4d1c, 0x4000, 
        0x2c06, 0x0000, 
        0x3a9a, 0xc703, 
        0xc0a8, 0x8226]
           

 對應的校驗和計算如下(Python腳本):

def checksum(head):
    sum = 0 
    for i in range(0, len(head)):
        sum = sum + (0xffff-head[i])
    #print "%4X"%sum

    sum = (sum>>16)+(sum & 0xffff) # why ? 
    #print "%4X"%(sum)
    return sum
           

 為什麼需要sum = (sum>>16)+(sum & 0xffff)這一步?

答:這是二進制反碼求和算法決定的。即計算校驗和時,若相加後最高位有進位,那麼不能舍棄,一定要加到低位,才能是結果正确。

現在,IP資料包的頭部為:

head = [0x45c0, 0x0028, 
        0x4d1c, 0x4000, 
        0x2c06, 0xBC87, 
        0x3a9a, 0xc703, 
        0xc0a8, 0x8226]
           

再調用checksum方法一次,将得到 全1 的最終結果。

轉載于:https://www.cnblogs.com/dachengxu/archive/2013/03/31/2991618.html