IP數據報首部checksum的計算


IP數據報首部checksum的計算

 

一、首先區別下面兩個概念:
(1)one's complement:正數=原碼,負數=反碼 
(2)two's complement:就是通常所指的補碼

 

二、計算ip首部校驗和

1.發送IP數據報計算checksum
(1)將校驗和字段置為0;
(2)對首部中(一般為20B)每個16位字進行二進制反碼求和;(這里的文字描述是有問題的,每個16bit進行二進制反碼求和,是要把16bit先去反碼再求和嗎?實際上是16bit逐個求和之后,再取反碼的意思)
(3)將(2)中得到的和再取反碼,即得checksum,寫入校驗和字段中。


抓個IP數據包,取IP數據報報頭部分(20B),數據如下:

 45 00 00 30 80 4c 40 00 80 06 b5 2e d3 43 11 7b cb 51 15 3d

下面我來計算一下校驗和:
(1)將校驗和字段置為0:
將b5 2e置為00 00,即變成: 
45 00 00 30 80 4c 40 00 80 06 00 00 d3 43 11 7b cb 51 15 3d

(2)反碼求和
 4500+0030+804c+4000+8006+0000+d343+117b+cb51+153d=34ace
 將將進位(3)加到低16位(4ace)上:0003+4ace=4ad1

(3)取反碼
 將4ad1取反得:checksum=b52e
 
2.接收IP數據報檢驗IP校驗和
(1)對首部中每個16 bit進行二進制反碼求和;
(2)將(1)中得到的和再取反碼 ,看是否為0.

接收到的IP數據報首部:
45 00 00 30 80 4c 40 00 80 06 b5 2e d3 43 11 7b cb 51 15 3d 
 
下面來驗證下:
(1)反碼求和

4500+0030+804c+4000+8006+b52e+d343+117b+cb51+153d=3fffc
0003+fffc=ffff

(2)取反碼:~ffff=0 正確
     
 
三、求IP數據報首部校驗碼代碼

已將IP首部校驗和0xb52e置為0x0000

#include<stdio.h>
void main()
{
int buff[10]={0x4500,0x0030,0x804c,0x4000,0x8006,0x0000,0xd343,0x117b,0xcb51,0x153d};
int checksum=0,i=0;
for(i=0;i<10;i++)
{
checksum+=buff[i];
}
printf("checksum=%x/n",checksum);
checksum=(checksum>>16)+(checksum & 0xffff);
checksum+=(checksum>>16);
checksum=0xffff-checksum;
printf("checksum=%04x/n",checksum);
}

 

IP校驗和計算

 

下面摘自《TCP/IP協議簇》的IP頭校驗和算法:

發送時:

1. 將校驗和字段置為0;

2. 將整個首部分為16bit的部分,求和;

3. 取反碼,填入到校驗和字段中;

接收時:

1. 直接將整個首部分為16bit的部分,求和;

2. 取反碼,若結果為0,取合法;否則丟棄;

這上面有兩個細節沒有描述清楚:

1. 計算時的字節順序(litter endian和big endian)問題;

2. 取和溢出時的改進計算方法;

根據實驗結果,及參考網絡上的資料,實際上幾乎現有所有的系統對校驗和算法已經有點小小的補充,也許《TCP/IP協議簇》這里沒有更新罷了,自我安慰吧,如下:

◆當發送IP包時,需要計算IP報頭的校驗和:

1、  把校驗和字段置為0;

2、  對IP頭部中的每16bit進行二進制求和;

3、  如果和的高16bit不為0,則將和的高16bit和低16bit反復相加,直到和的高16bit為0,從而獲得一個16bit的值;

4、  將該16bit的值取反,存入校驗和字段。

◆當接收IP包時,需要對報頭進行確認,檢查IP頭是否有誤,算法同上2、3步,然后判斷取反的結果是否為0,是則正確,否則有錯。

算法:

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM