關於協議首部校驗和的問題

尾田榮一郎發表於2016-06-17
   最近看謝希仁的《計算機網路》課本,裡面出現了5處小錯誤(具體的我寫到我的新浪微博裡了,詳見http://m.weibo.cn/1901976851/3983830128222967?sourceType=sms&from=1066095010&wm=20005_0002)最近又遇到一個問題,就是校驗和欄位,這個在IP協議和UDP裡面都有提到,它們使用的是同一個演算法(反碼求和),只是IP校驗的是IP首部,UDP校驗的是偽首部+首部+資料。具體是有兩個問題,按照字面含義,反碼求和,不應該是先求反碼,再求和,可是老謝的課本是先求和,最後對和求的反碼,我在網上查了相關資料,百度上好多人回答的是先求反碼再求和(當然百度的內容不能全信,你懂的),那麼問題來了,運算順序不一樣,對結果會不會有影響。第二個問題是老謝的課本在IP那兒說如果接收方收到以後再進行一次反碼求和,如果結果是全0,則沒有差錯,否則反之。在UDP也是同樣的情形,接收方收到以後也要進行反碼求和,如果結果是全1,則沒有差錯,否則反之。當然這個思路推理過來,似乎有些自相矛盾。(不過要是注意到細節的話,還是沒有問題的)下來我們具體看一個例子,看看到底是什麼樣子的。

首先求反碼沒有問題,就是把1變成0,把0變成1。求和這一部分的話除了要知道0加0等於0,1加0等於1,1加1等於0,並向高位產生進位,如果已經是最高位了,它的進位該怎麼處理,這時候要在原來結果上去加一個1(後面例子也會講到),最初要把校驗和欄位置為全0。這個共識達成了以後,我們就開始今天的例子。

為了簡化運算我們統一取4位2進位制數表示,比如原始資料是15和8,轉成四位二進位制就分別是1111和1000,當然最初的校驗和欄位是0000。首先我們用第一種方法,先求反碼,再求和。對於傳送方,15的反碼是0000,8的反碼是0111,初始的校驗和反碼是1111,然後把0000和0111和1111相加,得到的結果為0111(本來是0110但是最高位產生了一個進位,所以要在0110的基礎上加1)。所以最後得到的校驗和為0111,併傳送給接收方,接收方收到以後,也要對他們先求反碼,再求和,15的反碼是0000,8的反碼是0111,校驗和的反碼是1000,把0000和0111和1000相加,得到的結果為1111(最高位沒有進位),也就是結果是全1。然後我們先求和,最後對和求反碼,15是1111,8是1000,最初的校驗和是0000,我們對這三個數求和,結果是1000(本來是0111但是高位有一個進位,所以要加1)。最後對和1000取反碼結果為0111,所以最後的校驗和為0111,接收方收到 以後,也要對它們先求和,再求反碼。就是把1111,1000,0111三個數相加的結果為1111(本來是1110,但是最高位有一個進位1,所以要加1),最後對結果取反,結果是0000,也就是全0。 具體過程見下圖enter image description here 最終可以得出這樣一個結論:不管是先求反碼再求和,還是先求和再對和求反碼,計算出來的校驗和是相同的。但是對於差錯的標準不同,一個全0證明無差錯,一個要全1證明無差錯。(當然老謝這種計算思路比較權威,就是先求和,再對和求反碼)而且對於老謝這種先求和,再對和求反碼的,最後無差錯的標準是接收方計算出來的結果是全0。上面提到的課本里面的IP和UDP那個“自相矛盾”,仔細推敲的話還是沒有問題的,在IP那兒接收方要對資料求和以後,再對和求反碼,所以全0無差錯。而UDP那兒的接收方對資料求和以後,沒有提到對和求反碼,(當然這個細節很難注意到)如果這個和就是最終結果,所以全1無差錯,也是對的。

相關文章