1. 程式人生 > >學習:傳輸層之TCP協議

學習:傳輸層之TCP協議

一、TCP協議的特點

  • TCP是一種可靠的、面向連線的位元組流服務。源主機在傳送資料前需要先和目標主機建立連線。
  • TCP提供可靠交付的服務,通過TCP連線傳送的資料,無差錯、不丟失、不重複、並且按序列到達。且提供流量控制和擁塞控制。
  • 每一條TCP連線只能有兩個端點,每一條TCP連線只能是點對點的。
  • CP提全雙工通訊,允許通訊雙方的應用程序在任何時候都能傳送資料。TCP連線的兩端都設有傳送快取和接收快取用來臨時存放雙向通訊的資料。

二、TCP報文格式

這裡寫圖片描述
Source/Dest Port
源/目標埠號欄位:佔16位元。TCP協議通過使用”埠”來標識源端和目標端的應用程序。埠號可以使用0-65535之間的任何數字。在收到服務請求時,作業系統動態地為客戶端的應用程式分配埠號。在伺服器端,每種服務在”眾所周知的埠”(Well-Know Port)為使用者提供服務。

Sequence number
順序號欄位:佔32位元。用來標識從TCP源端向TCP目標端傳送的資料位元組流,它表示在這個報文段中的第一個資料位元組。 

Acknowledgement Number
確認號欄位:佔32位元。只有ACK標誌為1時,確認號欄位才有效。它包含目標端所期望收到源端的下一個資料位元組的序號。

Header Length
頭部長度欄位:佔4位元。給出頭部佔32位元的數目。沒有任何選項欄位的TCP頭部長度為20位元組;最多可以有60位元組的TCP頭部。

保留
佔6位,保留為今後使用,但目前應置為0。

標誌位欄位(U、A、P、R、S、F)
佔6bit各Bit的含義如下:
URG:緊急指標(urgent pointer)有效或無效。
ACK:說明確認號是否有效;1有效,0無效。
PSH:推送表示接收方應該儘快將這個報文段交給應用層不能再緩衝中停留,核心優先處理的報文。
RST:重建連線。
SYN:發起一個連線。
FIN:釋放一個連線。

Windows size
視窗大小欄位:佔16位元。視窗指的是傳送本報文段的一方的接收視窗就(不是自己的傳送視窗)。視窗值告訴對方:從本報文段首部中的確認好算起,接收方沒目前允許對方傳送的資料量。之所以要有這個限制,是因為接收方的資料快取空間是有限的。

Tcp checksum TCP
校驗和欄位:佔16位元。對整個TCP報文段,即TCP頭部和TCP資料進行校驗和計算,並由目標端進行驗證。

Urgent Pointer
緊急指標欄位:佔16位元。它是一個偏移量,和序號欄位中的值相加表示緊急資料最後一個位元組的序號。URG為1有效。

Options
選項欄位:佔32位元。可能包括”視窗擴大因子”、”時間戳”等選項。

Data
資料段:承載應用層的資料。

三、套接字

TCP的每一條連線都有兩個端點,那麼TCP連線的端點是什麼呢?不是主機,不是主機的IP地址,不是應用程序,也不是傳輸層的協議埠。TCP連線的端點叫做套接字(socket)。埠號拼接到IP地址即構成了套接字。因此套接字的表示方法是在在點分十進位制的IP地址後面寫上埠號,中間用冒號或逗號隔開。例如,若IP地址是192.168.10.1而埠號是80,那麼得到的套接字就是192.168.10.1:80

總之,TCP連線就是由協議軟體所提供的一種抽象,雖然有時為了方便,我們也可以說,在一個應用程序和另一個應用程序之間建立了一條TCP連線,但一定要記住:TCP連線的端點是套接字,即IP地址和埠號。也還應記住:同一個IP地址可以有多個不同的TCP連線,而同一個埠號也可以出現多個不同的TCP連線中。

四、TCP的連線建立

下圖畫出了TCP的建立連線的過程,主機A執行的事TCP客戶端程式,而B主機執行的事伺服器端程式。最初兩端的TCP程序都處於CLOSED(關閉)狀態。另外A是主動開啟而B是被動開啟。
這裡寫圖片描述
首先,B伺服器端會先建立傳輸控制塊TCB(transmission control block)傳輸控制塊儲存了每一個連線中的一些重要資訊,入TCP連線表,到傳送和接收快取的指標等等,準備接收客戶端程序的連線請求。然後伺服器程序就處於LISTEN(監聽)狀態,等待客戶端的連線請求。如有,即作出響應。

TCP的建立連線的過程稱為3次握手,如上圖所示:

1)A的TCP客戶程序也是首先建立傳輸控制模組TCB,然後向B發出連線請求報文段,其首部中的同步位SYN=1,並選擇序號seq=x,表明傳送資料時的第一個資料位元組的序號是x。這時,TCP客戶程序進入SYN-SENT(同步已傳送)狀態。

2)B的TCP收到連線請求報文段後,如同意,則發回確認。B在確認報文段中應使SYN=1,使 ACK=1,其確認號ack=x+1,自己選擇的序號seq=y。這時,TCP伺服器程序進入SYN-RCVD(同步收到)狀態。

3)A收到此報文段後向B給出確認,其ACK=1,確認號ack=y+1。A的TCP通知上層應用程序,連線已經建立。此時雙方的TCP程序狀態都是ESTABLISHED(已建立連線)標識建立連線成功。

其中A為什麼還要傳送一次確認呢?這主要是為了防止“已失效的連線請求報文段”突然又傳送到了B,因而產生錯誤。已失效的比如A發出連線請求但是由於在網路結點長時間滯留了,以致延誤到連線釋放以後的某個時間才到達B。本來這事一個早已失效的報文段。但B收到此失效的連線請求報文段後,就誤認為是A又發出一次新的連線請求。於是就向A發出確認報文段,同意建立連線。假定不採用三次握手,那麼只要B發出確認,新的連線就建立了。由於現在A並沒有發出建立連線的請求,因此不會理睬B的確認,也不會向B傳送資料。但B卻認為新的傳輸連線已經建立了,並一直等待A發來資料。B的許多資源就這樣浪費了。

下面給出了一個TCP建立連線的資料報,分析一個TCP建立連線的三次握手過程。如下:

IP 192.168.1.116.3337 > 192.168.1.123.7788: S3626544836:3626544836
IP 192.168.1.123.7788 > 192.168.1.116.3337: S 1739326486:1739326486 ack3626544837
IP 192.168.1.116.3337 > 192.168.1.123.7788: ack 1739326487,ack 1

第一次握手:192.168.1.116傳送位碼syn=1,隨機產生seqnumber=3626544836的資料包到192.168.1.123, 192.168.1.123由SYN=1知道192.168.1.116要求建立聯機;

第二次握手:192.168.1.123收到請求後要確認聯機資訊,向192.168.1.116傳送acknumber=3626544837,syn=1,ack=1,隨機產生seq=1739326486的包;

第三次握手:192.168.1.116收到後檢查ack number是否正確,即第一次傳送的seq number+1,以及位碼ack是否為1,若正確,192.168.1.116會再發送ack number=1739326487,ack=1,192.168.1.123收到後確認seq=seq+1,ack=1則連線建立成功

五、TCP的連線釋放

TCP連線釋放過程比較複雜,仍結合雙方狀態的改變來說明連線釋放的過程。如下圖畫出了釋放過程:
這裡寫圖片描述
資料傳輸結束後,通訊的雙方都可釋放連線,現在A和B都處於ESTABLISHED狀態。A的應用程序先向其TCP發出連線釋放報文段,並停止在傳送資料,主動關閉TCP連線。

1)A把連線釋放報文段首部的FIN=1,其序號seq=u,等待 B 的確認。這時A進入FIN-WAIT-1(終止等待1)狀態,等待B確認。

2)B收到連線釋放報文後即發出確認,確認號ack=u+1,而這個報文段自己的序號seq=v。然後B就進入CLOSE-WAIT(關閉等待)狀態。TCP伺服器程序通知高層應用程序。從A到B這個方向的連線就釋放了,TCP連線處於HALF-CLOSE(半關閉)狀態。B若傳送資料,A仍要接收。

3)A收到來自B的確認後,就進入FIN-WAIT-2(終止等待2)狀態,等待B發出的連線釋放報文段。若B已經沒有要向A傳送的資料,其應用程序就通知 TCP 釋放連線。這時B發出的連線釋放報文段必須是FIN=1,現假定B的序號為W(在半關閉狀態B可能又傳送了一些資料)。B還必須重複上次已傳送過的確認號ack=u+1。這時B就進入LAST-ACK(最後確認)狀態,等待A的確認。

4)A在收到B的連線釋放報文後,必須對此發出確認。在確認報文段中把ACK置1,確認號ack=w+1,而自己的序號是seq=u+1。然後進入到TIME-WAIT(時間等待)狀態。請注意,現在TCP連線還沒有釋放掉。必須經過時間等待計時器(TIME-WAIT TIMER)設定的時間2MSL後,A才進入到CLOSED狀態。時間MSL叫做最長報文段壽命(maximum segment lifetime),RFC 793建議設為2分鐘。但這完全是從工程上來考慮,對於現在的網路,MSL=2分鐘可能時間太長了一些。因此TCP允許不同的實現可根據具體情況使用更小的MSL值。因此,從A進入到TIME-WAIT狀態後,要進過4分鐘才能進入到CLOSED狀態,才能開始建立下一個新的連線,當A撤銷響應的傳輸控制塊後,就結束了這次的TCP連線。

為什麼A主機在TIME-WAIT狀態必須等待2MSL的時間呢?

第一,為了保證A傳送的最後一個ACK報文段能夠到達B。這個ACK報文段有可能丟失,因而使處在LAST-ACK狀態的B收到對已傳送的FIN+ACK報文段的確認。B會超時重傳這個FIN+ACK報文段,而A就能在2MSL時間內收到這個重傳的FIN+ACK報文段。接著A重傳一次確認,重新啟動2MSL計時器。最後,A和B都正常進入到CLOSED狀態。如果A在TIME-WAIT狀態不等待一段時間。那麼就無法收到B重傳的FIN+ACK報文,因而也不會再發送一次確認報文,這樣B就無法按照正常步驟進入CLOSED狀態。

TCP有一個特別的概念叫做half-close,這個概念是說由於TCP連線是全雙工的,因此每個方向都必須單獨進行關閉。這個原則是當一方完成它的資料傳送任務後就能傳送一個FIN來終止這個方向的連線。收到一個 FIN只意味著這一方向上沒有資料流動,一個TCP連線在收到一個FIN後仍能傳送資料。首先進行關閉的一方將執行主動關閉,而另一方執行被動關閉。

六、TCP有限狀態機

在TCP連線的建立和釋放中也都給出了TCP的各種狀態資訊,這裡為了更加清晰地看出TCP連線的各種狀態之間的關係,給出了下圖:
這裡寫圖片描述
這個圖給出了TCP的有限狀態機,圖中每一個方框即TCP可能具有的狀態。每個方框中的大寫英文字串是TCP標準的所使用的TCP連線狀態名。狀態之間的箭頭表示肯那個發生的狀態變遷。箭頭旁邊的字,表面引起這種變遷的原因,或表面發生狀態變遷後又出現什麼動作。注意:圖中有三種不同的箭頭,粗實線箭頭表示對客戶端程序的正常變遷,粗虛線箭頭表示對伺服器程序的正常變遷。另一種細線箭頭表示異常變遷。

狀態解釋:

  • CLOSED:關閉狀態。
  • LISTEN:偵聽來自遠方的TCP埠的連線請求。
  • SYN-SENT:再發送連線請求後等待匹配的連線請求。
  • SYN-RECEIVED:再收到和傳送一個連線請求後等待對方對連線請求的確認。
  • ESTABLISHED:代表一個開啟的連線。
  • FIN-WAIT-1:傳送FIN之後的狀態。
  • CLOSING:接收遠端TCP連線中斷的確認。
  • FIN-WAIT-2:接收到遠端TCP連線中斷的請求。
  • TIME-WAIT:等待足夠的時間2MSL以確保遠端TCP接收到連線中斷請求的確認。
  • CLOSE-WAIT:等待本地使用者發的連線中斷確認到連線中斷請求。
  • LAST-ACK:等待原來的發向遠端TCP的連線中斷請求的確認。