計算IP首部檢驗和

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

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

 

通過Wireshark抓到一個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 的最終結果。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章