校驗和算法

IP/ICMP/IGMP/TCP/UDP等協議的校驗和算法都是相同的,採用的都是將數據流視爲16位整數流進行重複疊加計算。爲了計算檢驗和,首先把檢驗和字段置爲0。然後,對有效數據範圍內中每個16位進行二進制反碼求和,結果存在檢驗和字段中,如果數據長度字節數爲奇數,那麼就在末尾則填充0。當收到數據後,同樣對有效數據範圍中每個16位數進行二進制反碼的求和。由於接收方在計算過程中包含了發送方存在首部中的檢驗和,因此,如果首部在傳輸過程中沒有發生任何差錯,那麼接收方計算的結果應該爲全0或全1(具體看實現了,本質一樣) 。如果結果不是全0或全1,那麼表示數據錯誤。

什麼是二進制反碼求和(1的補碼)
對一個無符號的數,先求其反碼,然後從低位到高位,按位相加,有溢出則向高位進1(跟一般的二進制加法規則一樣),若最高位有進位,則向最低位進1。
首先這裏的反碼好像跟我們以前學的有符號數的反碼不一樣(即正數的反碼是其本身,負數的反碼是在其原碼的基礎上,符號位不變,其餘各位取反),這裏不分正負數,直接每個位都取反!
上面加粗的那句是跟我們一般的加法規則不太一樣的地方:最高位有進位,則向最低位進1。確實有些疑惑,爲什麼要這樣做呢?仔細分析一下(爲了方便說明,以 4bit二進制反碼求和舉例),上面的這種操作,使得在發生加法進位溢出時,溢出的值並不是10000,而是1111。也即是當相加結果滿1111時溢出,這樣也可以說明爲什麼0000和1111都表示0了(你同樣可以發現,任何數與這兩個數做二進制反碼求和運算結果都是原數,這恰好符合數0的加法意義)。
另外關於二進制反碼求和運算需要說明的一點是,先取反後相加與先相加後取反,得到的結果是一樣的!,事實上我們的編程算法裏,幾乎都是先相加後取反。

1的補碼(相加和補取)
猜測是計算機相關語言.請參考這兩段文字:
It is the 1’s complement of the 1’s complement sum of all the 16-bit words in the TCP header and data.
這是關於TCP頭部校驗和字段(checksum field)的說明.句中的complement意思爲“補碼”.對於學習計算機科學的人來說,補碼不算什麼新鮮,現在新鮮的是這篇英語文章出現的是“1’s complement” ,翻譯出來應該是“1的補碼”,對於這個筆者以前也沒有碰到過,到網上查吧!網上查詢的結果,“1’s complement”關鍵字出現的不少,但都是英文關鍵字,沒有對應的中文翻譯與解釋,所以先看英語的,最後自己做解釋吧.
補碼:補碼是計算機中二進制數表達負數的辦法,這樣可以在計算機中把兩個數的減法變成加法.補碼形式有1的補碼和2的補碼,其中1的補碼用在IP、TCP的校驗和中;平時學生在計算機科學中學習的補碼是2的補碼(即正數的補碼和原碼相同,負數補碼按原碼相應的正數按位取反再加1).
只是平時中文教材及中文翻譯的書中,對此並不多加解釋,一律翻譯作補碼.比如《Computer Network》(Andrew S.Tanenbaum )在中國的翻譯版《計算機網絡》(清華大學出版社)對於TCP頭部的校驗和是這樣翻譯的:
(原文)The checksum algorithm is simply to add up all the 16-bit words in one's complement and then to take the one's complement of the sum.
(譯文)校驗和的算法是簡單地將所有16位字以補碼形式相加,然後再對相加和取補.
仔細對比一下本文最上部筆者所碰到的句子,和剛纔這個句子意思是一樣的.這個沒有註明是1的補碼,翻譯時只是以“補碼”說明,也許譯者並不想在這裏多費口舌,因爲說明1的補碼實在是一個比較麻煩的事情,筆者在這裏翻譯時還是把“1的補碼”給翻譯出來了,以讓大家注意這個1的補碼並不是平常學的那個2的補碼.
筆者只是在此討論翻譯,不是在討論補碼.1的補碼較複雜,如果有興趣,可以上網查找 RFC1071 ,這是TCP校驗和權威的官方說明.
發佈了40 篇原創文章 · 獲贊 36 · 訪問量 23萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章