TCP的運輸連接管理
TCP是面向連接的協議。運輸連接是用來傳送TCP報文的。TCP運輸連接的建立和釋放是每一次面向連接的通信中必不可少的過程。因此,運輸連接就有三個階段,即:連接建立、數據傳送和連接釋放。運輸連接的管理就是使運輸連接的建立和釋放都能正常地進行。
在TCP連接建立過程中要解決以下三個問題:
(1)要使每一方能夠確知對方的存在
(2)要允許雙方協商一些參數(如最大窗口值、是否使用窗口擴大選項和時間戳選項以及服務質量等)
(3)能夠對運輸實體資源(如緩存大小、連接表中的項目等)進行分配
TCP連接的建立采用客戶服務器方式。主動發起連接的建立的應用進程叫做客戶(client),而被動等待連接建立的應用進程叫做服務器(server)。
TCP的連接建立
TCP建立連接的過程叫做握手,握手

TCP連接釋放過程比較復雜,我們仍然結合雙方狀態的改變來闡明連接釋放的過程。
數據傳輸結束后,通信的雙方都可以釋放連接。現在A和B都處於ESTABLISHED狀態。A的應用進程先向其TCP發出連接釋放報文段,並停止再發送數據,主動關閉TCP連接。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就進入CLOSEWAIT(關閉等待)狀態。TCP服務器進程這時應通知高層應用進程,因而從A到B這個方向的連接就釋放了,這時的TCP連接釋放處於半關閉狀態,即A已經沒有數據要發送了,但 B若發送數據,A仍然要接收。這就是說,從B到A這個方向的連接並未關閉,這個狀態可能會持續一段時間。
A收到來自B的確認后,就進入FIN-WAIT(終止等待2)狀態,等待B發出的連接釋放報文段。
若B已經沒有要向A發送的數據,其應用進程就通知TCP釋放連接。這時候B發出的連接釋放報文必須使FIN=1.現假定B的序號為w(在半關閉狀態B可能又發送一些數據)。B還必須重復上次已發送過的確認號ack=u+1。這時B就進入LAST-ACK(最后確認)狀態,等待A的確認。
A在收到B的連接釋放報文段后,必須對此發出確認。在確認報文段中把ACK置1,確認號ack=w+1,而子集的序號是seq=u+1(根據TCP標准,前面發送過的FIN報文段要消耗一個序號)。然后進入到TIME-WAIT(時間等待)狀態。請注意,現在TCP連接還沒有釋放掉。必須經過時間等待計時器(TIME-WAIT timer)設置的時間2MASL后,ACIA進入到CLOSED狀態。時間MSL叫做最長報文段壽命,RFC793建議設為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早一些。
出現太多TIME_WAIT可能導致的后果:
在高並發短連接的TCP服務器上,當服務器處理完請求后立刻按照主動正常關閉連接。這個場景下,會出現大量socket處於TIMEWAIT狀態。如果客戶端的並發量持續很高,此時部分客戶端就會顯示連接不上。
我來解釋下這個場景。主動正常關閉TCP連接,都會出現TIMEWAIT。為什么我們要關注這個高並發短連接呢?有兩個方面需要注意:
① 高並發可以讓服務器在短時間范圍內同時占用大量端口,而端口有個0~65535的范圍,並不是很多,刨除系統和其他服務要用的,剩下的就更少了。
②在這個場景中,短連接表示“業務處理+傳輸數據的時間 遠遠小於 TIMEWAIT超時的時間”的連接。這里有個相對長短的概念,比如,取一個web頁面,1秒鍾的http短連接處理完業務,在關閉連接之后,這個業務用過的端口會停留在TIMEWAIT狀態幾分鍾,而這幾分鍾,其他HTTP請求來臨的時候是無法占用此端口的。單用這個業務計算服務器的利用率會發現,服務器干正經事的時間和端口(資源)被掛着無法被使用的時間的比例是 1:幾百,服務器資源嚴重浪費。(說個題外話,從這個意義出發來考慮服務器性能調優的話,長連接業務的服務就不需要考慮TIMEWAIT狀態。同時,假如你對服務器業務場景非常熟悉,你會發現,在實際業務場景中,一般長連接對應的業務的並發量並不會很高)
綜合這兩個方面,持續的到達一定量的高並發短連接,會使服務器因端口資源不足而拒絕為一部分客戶服務。
