電腦網路-5-10-TCP運輸連接管理
TCP的運輸連接管理
TCP是面向連接的通訊,運輸連接是用來傳送TCP報文的,TCP運輸連接的建立和釋放是每一次面向連接的通訊中必不可少的過程。因此,運輸連接有三個階段,即:建立連接,數據傳送,連接釋放,運輸連接的管理就是使運輸連接和釋放都能正常的進行。在TCP連接中主要解決以下問題:
-
要使每一方都能確認對方的存在。
-
要允許雙方協商一些參數(如最大窗口值,是否使用窗口擴大選項和時間戳選項以及服務品質等)。
-
能夠對運輸實體資源進行合理的分配(如快取大小,連接表中的項目等)。
TCP連接的建立採用客戶伺服器方式。主動發起連接建立的應用進程叫做客戶(client),而被動等待連接的應用進程叫做伺服器(server)。
TCP的連接建立
TCP建立連接的過程叫握手,握手需要客戶和伺服器之間交換三個TCP報文段。如下圖5-28。
假定主機A運行的是TCP客戶程式,而B運行的是TCP服務程式,最初兩端的連接處於CLOSE(關閉) 狀態,在本例中A主動打開連接,B被動打開連接。
TCP握手過程描述:
- 一開始,B的TCP伺服器進程先創建傳輸控制塊TCB(Transmission Control Block),準備接受客戶進程的連接請求,然後伺服器就處於LISTEN(監聽)狀態,等待客戶的連接請求,如果有,就做出響應。
- A的TCP客戶進程也是首先創立傳輸控制模組TCB,然後在建立連接的時候,向伺服器B發送連接請求報文段,這時候首部中的同步位SYN=1,同時選擇一個初始序號seq=x。TCP規定:SYN報文段(SYN=1的報文段)不能攜帶數據,但是要消耗掉一個序列號,這時候,TCP客戶端進程進入SYN-SENT同步已發送狀態。
- B收到連接請求的報文段,如果同意建立連接,則向A發送確認,在確認報文段SYN位=1,ACK位為1,確認號是ack=x+1,同時也為自己選擇一個初始序號seq=y,注意,這個報文段也不能攜帶數據,但是同樣要消耗一個序列號。這時候TCP伺服器進程處於SYN-RCVD(同步收到)狀態。
- TCP客戶進程收到B的確認後,還要給B給出確認,確認報文段的ACK=1確認號ack=y+1,而自己的序號seq=x+1。TCP的標準規定,ACK報文段可以攜帶數據,但如果不攜帶數據則不消耗序號,這種情況下,下一個數據報文段的序號仍然是seq=x+1,這時候,TCP連接已經建立連接,客戶端A進入ESTABLISHED(已建立連接狀態),
- B收到A的確認報文後,也進入ESTABLISHED狀態。
上面給出的連接過程叫做三次報文握手,注意,在圖中,當B發送給A的報文段,也可以拆分成兩個報文段,可以先發送確認報文段(ACK=1,ack=x+1),然後再發送一個同步報文段(SYN=1,seq=y),這樣的過程就變成了四報文握手,但效果是一樣的。
為什麼A最後還要發送一次確認呢?這主要是為了防止已失效的連接請求報文突然又傳送到B,因而產生錯誤。
所謂「已失效的連接請求報文段」是這樣產生的。考慮一種正常情況,A 發出連接請求,但因連接請求報文丟失而未收到確認。於是 A 再重傳一次連接請求。後來收到了確認,建立了連接。數據傳輸完畢後,就釋放了連接。A 共發送了兩個連接請求報文段,其中第一個丟失,第二個到達了 B,沒有「已失效的連接請求報文段」。
現假定出現一種異常情況,即 A 發出的第一個連接請求報文段並沒有丟失,而是在某些網路結點長時間滯留了,以致延誤到連接釋放以後的某個時間才到達 B。本來這是一個早已失效的報文段。但 B 收到此失效的連接請求報文段後,就誤認為是A又發出一次新的連接請求。於是就向 A 發出確認報文段,同意建立連接。假定不採用報文握手,那麼只要 B發出確認,新的連接就建立了。
由於現在 A 並沒有發出建立連接的請求,因此不會理睬 B 的確認,也不會向 B 發送數據。但 B 卻以為新的運輸連接已經建立了,並一直等待 A 發來數據。B 的許多資源就這樣白白浪費了。
採用三報文握手的辦法,可以防止上述現象的發生。例如在剛才的異常情況下,A 不會
向B的確認發出確認。B 由於收不到確認,就知道A並沒有要求建立連接。
TCP連接釋放
TCP連接釋放比較複雜,我們仍然結合雙方狀態的改變來闡明連接釋放的過程。
數據傳輸結束後,通訊的雙方都可釋放連接。現在 A 和 B 都處於 ESTABLISHED 狀態(圖5-29)。A 的應用進程先向其TCP發出連接釋放報文段,並停止再發送數據,主動關閉TCP 連接。A 把連接釋放報文段首部的終止控制位 FIN 置 1,其序號 seq = u,它等於前面已傳送過的數據的最後一個位元組的序號加 1。這時 A 進入 FIN-WAIT-1(終止等待 1)狀態,等待 B 的確認。請注意,TCP 規定,FIN 報文段即使不攜帶數據,它也消耗掉一個序號。
-
B伺服器收到連接釋放的報文段後立即發出確認,確認號為ack=u+1,而這個報文段自己的序號為v,等於B前面已傳過的數據的最後一個位元組+1,然後伺服器就進入CLOSE-WAIT(關閉等待)狀態,TCP伺服器進程這時候通知高層應用進程,因而從客戶端A到伺服器端B這個連接就釋放了,這時候的TCP連接窗檯處於半關閉狀態(HALF-CLOSE),A已經沒有數據發送給B了,但是B要使發數據,A仍然要接受,也就說,從B到A的方向的連接仍未關閉,這個狀態可能還要持續一段時間。 A收到來自B的確認後,就進入FIN-WAIT2(終止等待2)狀態,等待B發出的連接釋放報文段。若B已經沒有必要向A發送數據了,其應用進程就通知TCP釋放連接。這時候B發出的連接釋放報文段必須使FIN=1。現假設B的序號為w,B還重複上次已經發送過的確認號ack=u+1,這時候B就進入LAST-ACK(最後確認狀態),等待A的確認。A在收到B的連接釋放的時候,必須對此發出確認,在確認報文段中把ACK=1,確認號ack=w+1,自己的序號為seq=u+1,然後進入到TIME-WAIT(時間等待狀態),注意,現在的TCP並沒有斷開連接,而是必須經過時間等待計時器設置的2MSL(max segment lifetime),A才能進入CLOSED狀態,時間MSL叫做最長報文段壽命,RFC標準建議為2min。為什麼要設立時間等待狀態必須為2MSL呢?
- 為了保證客戶端發送額最後一個ACK報文段能夠到達B,這個ACK報文段有可能會丟失,因而使用LAST-ACK狀態的B收不到對已發送FIN+ACK報文的確認,B會超時重傳這個FIN+ACK報文段,而A就能在2MSL時間內收到這個重傳的FIN+ACK報文段,接著A重傳一次確認,重新啟動AMSL計時器。最後知道A和B都進入CLOSED狀態。
- 防止上面提到的已失效的連接請求報文段出現在本連接中,A在發完最後一個ACK報文段的時候,再經過2MSL時間,就可以是本連接持續的時間內產生的所有報文段都從網路中協消失。這樣就可以使下一個新的連接中不會出現這種舊的連接請求文。
除了時間等待計時器之外,還應該設有保活計時器(keep-live timer),有這樣的一個場景:客戶端已經主動與伺服器建立了TCP連接,但是後來客戶端的主機突然出現了故障,顯然,伺服器以後就不能在也接收到客戶端的數據了,因此,伺服器就沒有必要浪費資源繼續與出現故障的客戶端繼續保持相連。這就需要使用保活計時器,伺服器每收到一次客戶端請求的數據,就重新重置保活計數器,時間的設置通常是兩小時,若兩小時內沒有收到客戶端的數據,伺服器就發送一個探測報文段,以後每隔75s發送一個,若一連發送10個探測報文段後仍然沒有相應,伺服器就認為該客戶端出現了故障,就關閉這個連接。
TCP的有限狀態機)
為了更清晰地看出 TCP 連接的各種狀態之間的關係,圖 5-30 給出了 TCP 的有限狀態機。圖中每一個方框即 TCP 可能具有的狀態。每個方框中的大寫英文字元串是 TCP 標準所使用的 TCP 連接狀態名。狀態之間的箭頭表示可能發生的狀態變遷。箭頭旁邊的字,表明引起這種變遷的原因,或表明發生狀態變遷後又出現什麼動作。請注意圖中有三種不同的箭頭。粗實線箭頭表示對客戶進程的正常變遷。粗虛線箭頭表示對伺服器進程的正常變遷。另一種細線箭頭表示異常變遷。