tcp 偽頭部 結構 格式 校驗和

ForTechnology發表於2011-08-06
//tcp 偽頭部, 計算校驗和時需要
typedef struct
{
 unsigned long saddr; //源IP地址      
 unsigned long daddr; //目的IP地址       
 char mbz;                   // mbz = must be zero, 用於填充對齊
 char protocal;             //8位協議號       
 unsigned short tcpl;    // TCP包長度      
}psdheader_t;
TCP頭校驗和計算演算法詳解  

2010-06-23 08:02:24|  分類: 程式設計 |  標籤: |字號大中小 訂閱
我就不管是按“位”(bit)取反相加,還是按“1的補碼”相加了,總之
就是把需要進行校驗的“字串”加(+)起來,把這相加的結果取反當做
“校驗和” (Checksum),比如,相加的結果是0101,那麼“校驗和”就
是1010,驗證的時候呢,就是 0101+1010 = 1111 ,取反後,就是0
——如果驗證得“零”(0),就是正確的!

先將checksum欄位置零,然後按16位分組,計算2進位制反碼和,最後再求和的反碼!

為了計算一份資料包的IP檢驗和,首先把檢驗和欄位置為0。然後,對首部中每個16bit進行二進位制反碼求和(整個首部看成是由一串16bit的字組成),結果存在檢驗和欄位中。當收到一份IP資料包後,同樣對首部中每個16bit進行二進位制反碼的求和。由於接收方在計算過程中包含了傳送方存在首部中的檢驗和,因此,如果首部在傳輸過程中沒有發生任何差錯,那麼接收方計算的結果應該為全1。如果結果不是全1(即檢驗和錯誤),那麼IP就丟棄收到的資料包。但是不生成差錯報文,由上層去發現丟失的資料包並進行重傳。



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

1、  把校驗和欄位置為0;

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

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

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

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

 

演算法:

SHORT checksum(USHORT* buffer, int size)

{

unsigned long cksum = 0;

 

while(size>1)

{

    cksum += *buffer++;

    size -= sizeof(USHORT);

}

if(size)

{

    cksum += *(UCHAR*)buffer;

}

cksum = (cksum>>16) + (cksum&0xffff);  //將高16bit與低16bit相加

cksum += (cksum>>16);             //將進位到高位的16bit與低16bit 再相加

 

return (USHORT)(~cksum);

}

 

例項:

IP頭:  

              45 00    00 31

              89 F5    00 00

              6E 06    00 00(校驗欄位)

              DE B7   45 5D       ->    222.183.69.93

              C0 A8   00 DC     ->    192.168.0.220

計算:   

    4500 + 0031 +89F5 + 0000 + 6e06+ 0000 + DEB7 + 455D + C0A8 + 00DC =3 22C4

    0003 + 22C4 = 22C7

     ~22C7 = DD38      ->即為應填充的校驗和

當接受到IP資料包時,要檢查IP頭是否正確,則對IP頭進行檢驗,方法同上:

計算:

    4500 + 0031 +89F5 + 0000 + 6E06+ DD38 + DEB7 + 455D + C0A8 + 00DC =3 FFFC

    0003 + FFFC = FFFF

     ~FFFF = 00000     ->正確

TCP首部檢驗和與IP首部校驗和的計算方法相同,在程式中使用同一個函式來計算。

需要注意的是,由於TCP首部中不包含源地址與目標地址等資訊,為了保證TCP校驗的有效性,在進行TCP校驗和的計算時,需要增加一個TCP偽首部的校驗和,定義如下:

struct

{

unsigned long saddr; //源地址

unsigned long daddr; //目的地址

char mbz;//置空

char ptcl; //協議型別

unsigned short tcpl; //TCP長度

}psd_header;

然後我們將這兩個欄位複製到同一個緩衝區SendBuf中並計算TCP校驗和:

memcpy(SendBuf,&psd_header,sizeof(psd_header));

memcpy(SendBuf+sizeof(psd_header),&tcp_header,sizeof(tcp_header));

tcp_header.th_sum=checksum((USHORT *)SendBuf,sizeof(psd_header)+sizeof(tcp_header));

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/25897606/viewspace-704311/,如需轉載,請註明出處,否則將追究法律責任。

相關文章