重讀TCP/IP(5)之TCP頭部

TCP概述

前一篇講述了IP,它是一個不可靠的,無鏈接的,無序的,無流控的,只顧尋找最佳路由進行轉發,提供最好的傳輸,既然IP無論這些,是由於這些都由TCP來完成,IP層只須要傳送,無論到達,複雜度在於路由選擇,TCP接管了有序,有鏈接的,可靠的服務,複雜度也就在於如何有序,如何控制流量,使得傳輸可靠,兩個協議側重面不一樣,但卻又相輔相承,TCP保證正確的傳輸,IP保證最佳路徑傳輸,IP不保證到達,TCP保證到達。想要知道TCPIP不同的地方就須要瞭解它的頭部和IP有什麼區別。html

TCP頭部

Source port 源端口和Destination port 目的端口16位,告知主機該報文段是來自哪一個源端口以及傳給哪一個上層協議(應用層)目的端口的,進行TCP通訊,客戶端一般使用系統自動選擇的臨時端口號,而服務器則使用一些知名服務的端口號。python

應用程序的端口號和應用程序所在主機的IP地址統稱爲socket(套接字),IP:XX, 在互聯網上socket惟一標識每個應用程序,源端口+源IP+目的端口+目的IP稱爲套接字對,一對套接字就是一個鏈接,一個客戶端與服務器之間的鏈接。

Sequence Number 序列號:32位,一次TCP通訊(創建到斷開)過程當中某一個傳輸方向上的字節流的每一個字節的編號,它保證了TCP通訊的有序性,解決網絡包亂序的問題,因爲有了這個編號,接收端能夠根據這個序號進行確認,能夠保證每一個分段在原始數據包中的位置,初始序列號由本身定,然後緒的序列號由對端的ACK決定:SN_x = ACK_y (x的序列號=y發給xACK)算法

Acknowledgement Number確認號:32位,用來另外一方發送來的TCP報文段的確認響應,其值是收到的TCP報文段的序號+1,也是對端下一次發報文段過來的序號,指望對端以這個序號開始發送本身的分組,這樣能夠保證發送過來的報文是有序的,不然發送端不能確認以前的報文是否有被收到,而要決定是否重傳, ACK_y = SN_x+TCP_len+Flag(ACK的值是由對方的tcp_len+對方的seq值以及flag的值來決定,syn,fin都消耗一個序號,而ack無需任何代價,由於確認序號與ACK標誌是在一塊兒的,屬於TCP頭部一部分,不消耗序號)緩存

Head Length 報頭長度:4位,標識該TCP頭部有多少個32bit字節,這個跟IP報文中的HL同樣,都是計算頭部長度,最小IPTCP頭部都是20字節,值爲5,即4*5=20TCP最大頭部爲60字節, 16*4,通常狀況下TCP頭部爲32字節,20字節頭+12字節的options,這個字段有時又叫offset,數據偏移,它肯定了TCP數據在一個分組中從何開始服務器

Flag標誌位:網絡

·       URG標誌: urgent pointer是否有效,1表示該分段包含緊急數據socket

·         ACK  標誌:表示確認號是否有效,攜帶ACK標誌的TCP報文段爲確認報文段tcp

·         PSH標誌:發送方使用該標誌通知接收方將所收到的數據所有提交給接收進程,這裏的數據包括PUSH過去的,以及接收方已經接收的那些沒有PUSH標誌的其它數據,目的是讓接收端當即提交進程處理而不要判斷是否還會有額外的數據到達。提示接收應用程序當即從TCP接收緩衝器中讀走數據,一般對時效性比較高的服務,如telnet。也常見TCP分片中,一個報文段發不完,此時須要清空緩存,以備後面的大數據到來ide

·         RST 標誌:表示要求對方從新創建鏈接,一般發生在對端端口沒打開,對端會發給一個帶R標誌的復位報文段,TCP提供了一個異常終止的方法,就是發TCP報文段,還有一種狀況就是鏈接屬於半打開狀態,此時寫數據,會收到RST,由於鏈接並不真實存在性能

·         SYN 標誌:請求創建一個鏈接,主要是協商ISN,初始序列號,完成三次握手

·         FIN 標誌:表示通知對方,本端數據已傳完,要關閉鏈接,完成四次握手,成功關閉,與RST不一樣的是,這是正常的關閉,而不是異常

Window Size窗口大小:16位,它是TCP流量控制的一個手段,這裏說的窗口是接收通告窗口,即告訴對方本端TCP接收緩衝區還能容納多少字節的數據,這樣對方就須要控制發送數據的速度

Checksum 校驗和:TCP的校驗和由發送端填充,由接收端執行CRC算法是否獲得全1,以檢驗TCP報文段在傳輸過程當中是否損壞,它與IP的校驗和不一樣,IP是頭校驗,而TCP的校驗和不只是TCP頭部,還有TCP的數據,以及IP源地址,目的地址,協議(0x06,TCPsegment Length)計算而來,每兩個字節爲一單位進行反碼求和,其中協議爲低字節,TCP報文長度也爲單低字節進行反碼求和,高位溢出加到低位

#/usr/bin/env python

def checksum(*aList):
    sum = 0x0
    for i in range(len(aList[0])):                         #aList[0]=alist
        if i%2 == 0:
            aList[0][i]=aList[0][i]<<8                     #奇數位左移8位,成爲高8位字節
    for i in aList[0]:
        sum = sum+i                                        #求和
        sum=(sum>>16)+(sum&0xffff)                         #循環相加,溢出就加到低位
        result = 2**16-1-sum                               #算反碼=2**模-原碼
        result = hex(result)                               #十六進制轉換
    return result

 

alist = [0xc0,0xa8,0x02,0x65,                              #192.168.2.101 源IP

         0xc0,0xa8,0x02,0x6f,                              #192.168.2.111 目的IP

         0x11,0xbf,0x1f,0x40,0x12,                         #從0x11開始到0x02都是TCP

         0xad,0xd2,0xf9,0x00,0x00,0x00,0x00,

         0x80,0x02,0xff,0xff,0x00,0x00,0x00,               #0xff後面的0x00,0x00是由於發端算校驗和先填校驗碼爲0,隨後算出來的值再到收端進行計算可得ffff

         0x00,0x02,0x04,0x05,0xac,0x01,0x03,

         0x03,0x02,0x01,0x01,0x04,0x02,                    

         0x00,0x20,0x00,0x06]                              #0x00,0x20 TCP報文長度(頭和數據),因爲如今沒有數據,所以只有頭+選項共32字節,0x20,做爲低字節,所以前面加0x00
                                                           #0x00,0x06 TCP協議號,做爲低字節,前面補0x00
print checksum(alist)

 ---------------------------------------------------------------------------

0xd253

Urgent Point 緊急指針:16位,是一個正的偏移量,它和序號字段的值相加表示最後一個緊急數據的下一字節的序號,所以確切的說是一個緊急偏移,TCP是字節流不存在優先級,可是能夠設置緊急位表示該報文有緊急數據,經過緊急指針知道這個報文中緊急數據的最後一個字節,可是並不知道這個報文中緊急數據的具體位置,由於初始位置不能肯定,有可能前面有普通數據。

options選項:TCP的選項是可變的,可是最多隻包含40個字節,由於TCP頭部最大60字節,固定部分20字節,選項的結構以下,全部的選項都遵循下面的格式

kind(1字節) length(1字節)                         info(n字節)           

選項的第一個字段爲Kind類型,有的選項沒有lengthinfo, 有的都有,但總共分爲7種選項

Kind=0是選項表結束選項

Kind=1是空操做NOP,通常用於將TCP的頭部填充爲4字節的整數倍

Kind=2是最大報文段長度,TCP鏈接初始化時會協商MSS(max segment size),TCP模塊一般設置爲1460,由於以太網最大數據報爲1500IP20 TCP20,最大段長就爲1460,這也就避免了IP分片,也就是咱們說的在TCP應用中通常看不到IP分片的緣由

Kind=3窗口擴大因子,雖然窗口大小在鏈接時能夠協商,但窗口遠不止65535,當窗口大小爲N,當移位數爲M時,窗口大小在實際傳輸中是N*2**M

Kind=4是選擇性確認(Selective Acknowledgement, SACKTCP重傳機制指的是若是某個TCP報文丟失,TCP會重傳最後確認的TCP報文段的後緒報文段,但以前正確傳輸的報文段也要重傳,這就下降了性能,SACK可使TCP只重傳丟失的報文段,而不用把全部未確認的報文都重傳,鏈接時會選擇是否啓用SACK技術

Kind=5SACK實際工做的選項,該選項的參數告訴發送方已經收到並緩存的不連續的數據塊,從而讓發送端能夠據此檢查並重發丟失的數據塊,每一個塊邊沿包含4個字節,每一個塊的左邊沿表示不連續塊的的第一個數據號,右邊沿不連續塊的最後一個數據的序號的下一個序號,這樣一對參數之間的數據就是沒有收到的塊,一個塊信息佔用8字節,TCP頭部最多隻包含4個這樣的不連續塊,由於4*8+2<40

Kind=8是時間戳選項,該項提供較爲準確的,通訊雙方之間的迴路時間(RTT),爲流量控制提供重要信息,而且也爲SN的迴繞提供信息,在一個帶寬很高的環境中,充號最大爲65535,很短的時間,序號就會耗盡從而從0開始,有了timestamp後,咱們就能夠避免一樣的序號的包如何辨別前後的問題

參考:

http://www.kuqin.com/shuoit/20140611/340486.html TCP的那些事兒上
http://www.kuqin.com/shuoit/20140611/340485.html TCP的那些事兒下
TCP/IP guide
TCP/IP 協議卷1
相關文章
相關標籤/搜索