(二十九)運輸層--TCP的運輸連接管理

TCP的運輸連接管理

TCP是面向連接的協議。運輸連接是用來傳送TCP報文的。TCP運輸連接的建立和釋放是每一次面向連接的通信中必不可少的過程。因此,運輸連接就有三個階段,即:連接建立、數據傳送、連接釋放。運輸連接的管理就是使運輸連接的建立和釋放都能正常的進行。

在TCP連接建立過程中要解決以下三個問題:
(1)要使每一方能夠確知對方的存在
(2)要雙方協商一些參數(如最大窗口值、是否使用窗口擴大選項和時間戳選項以及服務質量等)
(3)能夠對運輸實體資源進行分配(如緩存大小、連接表中的項目等)

TCP連接的建立採用客戶服務器方式。主動發起連接建立的應用進程叫做客戶,而被動等待連接建立的應用進程叫做服務器。

TCP的連接建立

TCP建立連接的過程叫做握手,握手需要在客戶和服務器之間交換3個TCP報文段,下圖是三報文握手建立TCP連接的過程。

假定主機A運行的是TCP客戶程序,而B運行TCP服務器程序。最初兩端的TCP進程都處於 CLOSED(關閉) 狀態。圖中在主機下面的方框分別是TCP進程所處的狀態。請注意,在本例中,A主動打開連接,B被動打開連接。

一開始,B的TCP服務器進程先創建傳輸控制塊TCB。準備接受客戶進程的連接請求。然後服務器進程就處於 LISTEN(收聽)狀態,等待客戶的連接請求。如有,即作出響應。

A的TCP客戶進程也是首先創建傳輸控制模塊TCB。然後,在打算建立TCP連接時,向B發出連接請求報文段,這時首部中的同步位 SYN = 1,同時選擇一個初始序號 seq = x。TCP規定,SYN 報文段(即SYN = 1 的報文段)不能攜帶數據,但要消耗掉一個序號。這時,TCP客戶進程進入 SYN-SENT (同步已發送)狀態。

B收到連接請求報文段後,如同意建立連接,則向A發送確認。在確認報文段中應把 SYN 位和 ACK 位都置1,確認號 ack = x + 1,同時也爲自己選擇一個初始序號 seq = y。請注意,這個報文段也不能攜帶數據,但同樣要消耗掉一個序號。這時TCP服務器進程進入 SYN-RCVD (同步收到)狀態。

TCP客戶進程收到B的確認後,還要向B給出確認。確認報文段的ACK置1,確認號ack = y + 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的連接釋放

數據傳輸結束後,通信的雙方都可釋放連接。現在A和B都處於 ESTABLISHED 狀態。A的應用進程先向其TCP發出連接釋放報文段,並停止再發送數據,主動關閉TCP連接。A把連接釋放報文段首部的終止控制位 FIN 置1,其序號 seq = u。它等於前面已傳送過的數據的最後一個字節的序號加1。這時A進入 FIN-WAIT-1(終止等待1) 狀態,等待B的確認。TCP規定, FIN 報文段即使不攜帶數據,它也消耗掉一個序號。

B收到連接釋放報文段後即發出確認,確認號 ack = u + 1,這個報文段的序號是 v,等於B前面已傳送過的數據的最後一個字節的序號加1。然後B就進入 CLOSE-WAIT(關閉等待)狀態。TCP服務器進程這時應通知高層應用進程,因而從A到B這個方向的連接就釋放了,這時的TCP連接處於半關閉狀態(half-close),即A已經沒有數據要發送了,但B若發送數據,A仍要接收。也就是說,從B到A這個方向的連接並未關閉,這個狀態可能會持續一段時間。

A收到來自B的確認後,就進入 FIN-WAIT-2(終止等待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(TCP規定,前面發送過的 FIN 報文段要消耗一個序號)。然後進入到 TIME-WAIT(時間等待)狀態。現在TCP連接還沒有釋放掉。必須經過時間等待計時器設置的時間2MSL後,A才進入到 CLOSED 狀態。時間MSL叫做最長報文段壽命,RFC 793 建議設爲2分鐘。但這完全是從工程上來考慮的。對於現在的網絡,MSL = 2分鐘可能太長了。因此TCP允許不同的實現可根據具體情況使用更小的MSL值。從A進入到 TIME-WAIT 狀態後,要經過4分鐘才能進入到 CLOSED 狀態,才能開始建立下一個新的連接。當A撤銷相應的傳輸控制塊TCB後,就結束了這次的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 狀態不等待一段時間,而是在發送完ACK報文段後立即釋放連接,那麼就無法收到B重傳的 FIN + ACK 報文段,因而也不會再發送一次確認報文段。這樣,B就無法按照正常步驟進入 CLOSED 狀態。

第二,防止前面提到的“已失效的連接請求報文段”出現在本連接中。A在發送完最後一個 ACK 報文段後,再經過時間 2MSL,就可以使本連接持續的時間內所產生的所有報文段都從網絡中消失。這樣就可以使下一個新的連接中不會出現這種舊的連接請求報文段。

B只要收到了A發出的確認,就進入 CLOSED 狀態。同樣,B在撤銷相應的傳輸控制塊TCB後,就結束了這次的TCP連接。B結束TCP連接的時間要比A早一些。

上述的TCP連接釋放過程是四報文握手。

除時間等待計時器外,TCP還設有一個保活計時器。設想有這樣的情況:客戶已主動與服務器建立了TCP連接。但後來客戶端的主機突然出現故障。顯然,服務器以後就不能再收到客戶發來的數據。因此,應當有措施使服務器不要再白白等待下去。這就是使用保活計時器。服務器每收到一次客戶的數據,就重新設置保活計時器,時間的設置通常是2小時。若兩小時沒有收到客戶的數據,服務器就發送一個探測報文段,以後則每隔75秒發送一次。若一連發送10個探測報文段後仍無客戶的響應,服務器就認爲客戶端出了故障,接着就關閉這個連接。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章