TCP/IP校驗和


1. IP

https://www.cnblogs.com/xiehy/p/3166953.html

IP數據包也叫IP報文分組,傳輸在ISO網絡7層結構中的網絡層,它由IP報文頭和IP報文用戶數據組成,IP報文頭的長度一般在2060個字節之間,而一個IP分組的最大長度則不能超過65535個字節。 
下圖為IP分組的報文頭格式,報文頭的前20個字節是固定的,后面的可變。

 

版本:占4位(bit

IP協議的版本號。目前的主要版本為IPV4,即第4版本號,也有一些教育網和科研機構在使用IPV6。在進行通信時,通信雙方的IP協議版本號必須一致,否則無法直接通信。 

首部長度:占4位(bit

IP報文頭的長度。最大的長度(即4bit都為1時)為15個長度單位,每個長度單位為4字節(TCP/IP標准,DoubleWord),所以IP協議報文頭的最大長度為60個字節,最短為上圖所示的20個字節。

服務類型:占8位(bit

用來獲得更好的服務。其中的前3位表示報文的優先級,后面的幾位分別表示要求更低時延、更高的吞吐量、更高的可靠性、更低的路由代價等。對應位為1即有相應要求,為0則不要求。

總長度:16位(bit

指報文的總長度(包括報文頭)。注意這里的單位為字節,而不是4字節,所以一個IP報文的的最大長度為65535個字節。

標志(flag

該字段用於標記該報文是否為分片(有一些可能不需要分片,或不希望分片),后面是否還有分片(是否是最后一個分片)。

片偏移

指當前分片在原數據報(分片前的數據報)中相對於用戶數據字段的偏移量,即在原數據報中的相對位置。 

生存時間:TTLTime to Live

該字段表明當前報文還能生存多久。每經過1ms或者一個網關,TTL的值自動減1,當生存時間為0時,報文將被認為目的主機不可到達而丟棄。使用過Ping命令的用戶應該有印象,在windows中輸入ping命令,在返回的結果中即有TTL的數值。

協議

該字段指出在上層(網絡7層結構或TCP/IP的傳輸層)使用的協議,可能的協議有UDPTCPICMPIGMPIGP等。 

首部校驗和

用於檢驗IP報文頭部在傳播的過程中是否出錯,主要校驗報文頭中是否有某一個或幾個bit被污染或修改了。

IP地址:32位(bit

4個字節,每一個字節為0255之間的整數,及我們日常見到的IP地址格式。 

目的IP地址:32位(bit

4個字節,每一個字節為0255之間的整數,及我們日常見到的IP地址格式。

 

/*IP頭定義,共20個字節*/
typedef struct _IP_HEADER
{
 char m_cVersionAndHeaderLen;       //版本信息(4),頭長度(4)
 char m_cTypeOfService;            // 服務類型8
 short m_sTotalLenOfPacket;        //數據包長度
 short m_sPacketID;              //數據包標識
 short m_sSliceinfo;               //分片使用
 char m_cTTL;                  //存活時間
 char m_cTypeOfProtocol;          //協議類型
 short m_sCheckSum;             //校驗和
 unsigned int m_uiSourIp;          //ip
 unsigned int m_uiDestIp;          //目的ip
} __attribute__((packed))IP_HEADER, *PIP_HEADER ;

2. IP校驗和

https://www.cnblogs.com/yd1227/archive/2011/06/30/2094309.html

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

1、  把校驗和字段置為0

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

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

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

3. TCP head

https://www.cnblogs.com/li-hao/archive/2011/12/07/2279912.html

 

源端口:  長度為16位,2個字節。

目的端口:  長度為16位,2個字節。

    IP實現了點到點的數據通信,而TCP實現的是端到端的通信。

    通信端用一個IP與端口號來唯一標識。(其實端口號就是用來標識同一主機中的不同進程。)

    IP協議負責將數據傳輸到目標主機,而TCP可以根據數據報中的端口號,將數據交給相應的程序進行處理。

 

序列號: 長度32位,4個字節。

確認序列號:長度32位,4個字節。

頭部長度:該字段占用4位,用來表示報文首部的長度,單位是4Byte。如:headLen = ((packet[12]>>4)&0x0F)*4;

預留6位:長度為6位,作為保留字段,暫時沒有什么用處。

 

URG:長1位,表示緊急指針字段有效;

ACK:長1位,置位表示確認號字段有效;

PSH:長1位,表示當前報文需要請求推(push)操作;

RST:長1位,置位表示復位TCP連接;

SYN:長1位,用於建立TCP連接時同步序號;

FIN:長1位,用於釋放TCP連接時標識發送方比特流結束;

 

窗口大小:長度為16位,2個字節。

校驗和:長度為16位,2個字節。

緊急指針:長度為16位,2個字節。

以上是TCP包頭必須要有的字段,也稱固有字段,長度為20個字節。

可選項:此項是可選項(可有可無),解包時得具體分析(TCP包頭的一部分)

 

/*TCP頭定義,共20個字節*/
typedef struct _TCP_HEADER
{
 short m_sSourPort;              // 源端口號16bit
 short m_sDestPort;              // 目的端口號16bit
 unsigned int m_uiSequNum;         // 序列號32bit
 unsigned int m_uiAcknowledgeNum;  // 確認號32bit
 short m_sHeaderLenAndFlag;        // 4位:TCP頭長度;中6位:保留;后6位:標志位
 short m_sWindowSize;            // 窗口大小16bit
 short m_sCheckSum;              // 檢驗和16bit
 short m_surgentPointer;           // 緊急數據偏移量16bit
}__attribute__((packed))TCP_HEADER, *PTCP_HEADER;


/*TCP頭中的選項定義

kind(8bit)+Length(8bit,整個選項的長度,包含前兩部分)+內容(如果有的話)

KIND = 1表示 無操作NOP,無后面的部分

  2表示 maximum segment   后面的LENGTH就是maximum segment選項的長度(以byte為單位,1+1+內容部分長度)

  3表示 windows scale     后面的LENGTH就是 windows scale選項的長度(以byte為單位,1+1+內容部分長度)

  4表示 SACK permitted    LENGTH2,沒有內容部分

  5表示這是一個SACK     LENGTH2,沒有內容部分

  8表示時間戳,LENGTH10,含8個字節的時間戳
*/

typedef struct _TCP_OPTIONS
{
 char m_ckind;
 char m_cLength;
 char m_cContext[32];
}__attribute__((packed))TCP_OPTIONS, *PTCP_OPTIONS;

4. TCP校驗和

TCP頭前加一個偽首部,其它步驟和IP類似。

 

        unsigned short CheckSum(unsigned short *_pBuff, int _Size)

        {

            unsigned int ckSum = 0;

 

            unsigned short *tmpBuff = _pBuff;

            int tmpSize = _Size;

 

            while (tmpSize > 1)

            {

                ckSum += *tmpBuff ++;

                tmpSize -= sizeof(unsigned short);

            }

 

            if (tmpSize > 0)

            {

                ckSum += *(unsigned char*)tmpBuff;

            }

 

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

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

 

            return (unsigned short)(~ckSum);

        }

 

5. 檢驗和更新

https://blog.csdn.net/qq_43395215/article/details/103414009

如果在報文的轉發路徑中遇到需要修改iptcp中部分報文字段,那么校驗和需要重新計算。

當修改只是一小部分時,可以用下列方法更新校驗和。

IP頭校驗和、TCP/UDP校驗和更新

 

 

unsigned short updateCheckSum(unsigned short wOldCheckSum, unsigned short wOld, unsigned short wNew) {

    unsigned int dwCheckSum = wOldCheckSum + wOld + (~wNew & 0xFFFF);

    dwCheckSum = (dwCheckSum >> 16) + (dwCheckSum & 0xFFFF);

    dwCheckSum +=  (dwCheckSum >> 16);

    return  (unsigned short)dwCheckSum;

}

 

unsigned short updateCheckSum32(unsigned short wOldCheckSum, unsigned int dwOld, unsigned int dwNew) {

    return UpdateCheckSum(UpdateCheckSum(wOldCheckSum, (unsigned short) (dwOld >> 16), (unsigned short) (dwNew >> 16)), (unsigned short) dwOld, (unsigned short) dwNew);

}


免責聲明!

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



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