原創博文,轉載請注明出處。
在學習TCP/IP 詳解的過程中遇到了不止一次的關於檢驗和的概念,在吸取了他人理解的前提下,我決定用Wireshark 進行抓包分析。
首先我們得知道IP數據包格式
首先把檢驗和字段置為 0 。然后,對首部中每個 16 bit 進行二進制反碼求和(整個首部看成是由一串 16 bit的字組成),結果存在檢驗和字段中。當收到一份I P數據報后,同樣對首部中每個 16 bit進行二進制反碼的求和。由於接收方在計算過程中包含了發送方存在首部中的檢驗和,因此,如果首部在傳輸過程中沒有發生任何差錯,那么接收方計算的結果應該為全 1。如果結果不是全1 (即檢驗和錯誤),那么I P就丟棄收到的數據報。但是不生成差錯報文,由上層去發現丟失的數據報並進行重傳。
再來看看Wireshark抓取結果
觀察此圖,我們可以看到這是一個源地址為123.151.152.231 目的地址為10.22.66.206即為本機地址的IP數字報傳送。
注意圖中標深藍顏色的數字,每當我們點擊分類信息時,下方的數字就會跟隨着發生變化,因此我們就可以得到IP數據報的內容。、
解釋如下:(本內容部分取自博客園)
版本號4,占了4位,表示ipv4.
接下來是包頭長度,又占了4位,指明ipv4協議包頭長度的字節數包含多少個32位。由於IPv4
的包頭可能包含可變數量的可選 項,所以這個字段可以用來確定IPv4數據報中數據部分的偏
移位置。IPv4包頭的最小長度是20個字節,因此IHL這個字段的最小值用十六進制表示就是5
(5x4(4個字節32位) = 20字節)。就是說,它表示的是包頭的總字節數是4字節的倍數。
圖中即為header length為20表示是20個字節,所以經過計算此處用十六進制表示為5,二進制
表示為1001。
再往下是服務類型為0x00。
服務類型此處一共占了8位,涵義如下:
過程字段: 3位,設置了數據包的重要性,取值越大數據越重要,取值范圍為:0(正常)~ 7(網絡控制)
延遲字段: 1位,取值:0(正常)、1(期特低的延遲)
流量字段: 1位,取值:0(正常)、1(期特高的流量)
可靠性字段: 1位,取值:0(正常)、1(期特高的可靠性)
成本字段: 1位,取值:0(正常)、1(期特最小成本)
未使用: 1位
接着是總長度total length:十六進制是0x0028
標識字段:占16位。IP軟件在存儲器中維持一個計數器,每產生一個數據報,計數器就加1,並將此值賦給標識字段。
但這個“標識”不是序號,因為IP是無連接服務,數據報不存在按序接收的問題。當數據報由於長度超過網絡的MTU而必須分片時,
這個標識字段的值就被復制到所有的數據報片的標識字段中。相同的標識字段的值使分片后的各數據報片最后能正確地重裝成為原來的數據報
此處值為0xcf59
標志(flag):占3位,但目前只有兩位有意義。
標志字段中的最低位為MF(More Fragment)。MF=1即表示后面“還有分片”的數據報。MF=0表示這已是若干數據報片中的最后一個。
標志字段中間的一位記為DF(Don't Fragment),意思是“不能分片”。只有當DF=0時才允許分片。
此處值為0x02即010表示不能分片,即don't Fragment
13位片偏移:當數據分組時,它和更多段位(MF, More fragments)進行連接,幫助目的主機將分段的包組合
此處值為0x000
8位生存時間即ttl,表示數據包在網絡上生存多久,每通過一個路由器該值減一,為0時將被路由器丟棄。此處為0x33 十進制為51
8位協議:8位,這個字段定義了IP數據報的數據部分使用的協議類型。常用的協議及其十進制數值包括ICMP(1)、TCP(6)、UDP(17)。此處為tcp。
源端ip:123.151.152.231 0x7b97 0x98e7
目標ip:10.22.66.206 0x0a16 0x42ce
注意上面的0x1714就是我們的檢驗和,這個就是我們發送端的檢驗和。
到此,首部的數據基本確定清楚。
接下來我們講一下檢驗和算法:
0和0相加是0,0和1相加是1,1和1相加是0但要產生一個進位1,加到下一列.若最高位相加后產生進位,則最后得到的結果要加1.
在發送數據時,為了計算IP數據包的校驗和。應該按如下步驟:
(1)把IP數據包的校驗和字段置為0;
(2)把首部看成以16位為單位的數字組成,依次進行二進制反碼求和;
(3)把得到的結果存入校驗和字段中。
在接收數據時,計算數據包的校驗和相對簡單,按如下步驟:
(1)把首部看成以16位為單位的數字組成,依次進行二進制反碼求和,包括校驗和字段;
(2)檢查計算出的校驗和的結果是否等於零(反碼應為16個0);
(3)如果等於零,說明被整除,校驗和正確。否則,校驗和就是錯誤的,協議棧要拋棄這個數據包。
網上找了一個簡單點的例子先來看一下
原始數據為 1100 , 1010 , 0000(校驗位)
那么把他們按照4bit一組進行按位取反相加。 1100取反0011 , 1010取反是0101,0011加上0101 是1000,填入到校驗位后
1100 , 1010 , 1000
那么這個就是要發送的數據。收到數據后同樣進行按位取反相加。0011+0101+0111 =1111;全為1表示正確
第二種方法就是先直接相加再取反。
我們使用第二種:
先計算發送端的檢驗和,我們先令檢驗和為0x0000,然后進行運算4500+0028+cf59+4000+3306+0000+7b97+98e7+0a16+42ce然后將運算結果取反,最終得到數值0x1714,將其存入檢驗和字段中。
接收端收到一個IP數字報時,將進行4500+0028+cf59+4000+3306+1714+7b97+98e7+0a16+42ce運算,如果最終結果全為1,代表檢驗和無錯誤,否則丟棄收到的數據包。