1. 程式人生 > >TCP/IP詳解--TCP三次握手建立連線與四次握手終止連線

TCP/IP詳解--TCP三次握手建立連線與四次握手終止連線

1.TCP連線的建立 (1)首先是伺服器初始化的過程,從CLOSED(關閉)狀態開始通過順序呼叫SOCKETBINDLISTENACCEPT原語建立Socket套接字,進入LISTEN(監聽)狀態,等待客戶端的TCP傳輸連線請求。

     (2)客戶端最開始也是從CLOSED狀態開始呼叫SOCKET原語建立新的Socket套接字,然後在需要再呼叫CONNECT原語,向伺服器傳送一個將SYN欄位置1(表示此為同步資料段)的資料段(假設初始序號為i),主動開啟埠,進入到SYNSENT(已傳送連線請求,等待對方確認)狀態。

   TCP傳輸連線建立的三次握手過程

     (3)伺服器在收到來自客戶端的

SYN資料段後,發回一個SYN欄位置1(表示此為同步資料段),ACK欄位置1(表示此為確認資料段),ack(確認號)=i+1的應答資料段(假設初始序號為j),被動開啟埠,進入到SYN RCVD(已收到一個連線請求,但未進行確認)狀態。這裡要注意的是確認號是i+1,而不是i,表示伺服器希望接收的下一下資料段序號為i+1

     (4)客戶端在收到來自伺服器的SYN+ACK資料段後,向伺服器傳送一個ACK=1(表示此為確認資料段),序號為i+1ack=j+1的確認資料段,同時進入ESTABLISHED(連線建立)狀態,建立單向連線。要注意的是,此時序號為i+1,確認號為j+1,表示客戶端希望收到伺服器的下一個資料段的序號

j+1

     (5)伺服器在收到客戶端的ACK資料段後,進入ESTABLISHED狀態,完成雙向連線的建立。

雙方同時主動連線的TCP連線建立過程

     正常情況下,傳輸連線都是由一方主動發起的,但也有可能雙方同時主動發起連線,此時就會發生連線碰撞,最終只有一個連線能夠建立起來。因為所有連線都是由它們的端點進行標識的。如果第一個連線請求建立起一個由套接字(x,y)標識的連線,而第二個連線也建立了這樣一個連線,那麼在TCP實體內部只有一個套接字表項。

      當出現同時發出連線請求時,則兩端幾乎在同時傳送一個SYN欄位置1的資料段,並進入SYN_SENT狀態。當每一端收到SYN

資料段時,狀態變為SYN_RCVD,同時它們都再發送SYN欄位置1ACK欄位置1的資料段,對收到的SYN資料段進行確認。當雙方都收到對方的SYN+ACK資料段後,便都進入ESTABLISHED狀態。圖10-39顯示了這種同時發起連線的連線過程,但最終建立的是一個TCP連線,而不是兩個,這點要特別注意。


10-39 同時發起連線的TCP連線建立流程

      從圖中可以看出,一個雙方同時開啟的傳輸連線需要交換4資料段,比正常的傳輸連線建立所進行的三次握手多交換一個數據段。此外要注意的是,此時我們沒有將任何一端稱為客戶或伺服器,因為每一端既是客戶又是伺服器。


2.TCP連線的釋放            在資料傳輸完畢之後,通訊雙方都可以發出釋放連線的請求。釋放連線的過程為如上圖所示:      1)資料傳輸結束後,主機A的應用程序先向其TCP發出釋放連線請求,不在傳送資料。TCP通知對方要釋放從A到B的連線,將發往主機B的TCP報文段首部的終止位元FIN置為1,序號u等於已傳送資料的最後一個位元組的序號加1。      2)主機B的TCP收到釋放連線通知後發出確認,其序號為u+1,同時通知應用程序,這樣A到B的連線就釋放了,連線處於半關閉狀態。主機B不在接受主機A發來的資料;但主機B還向A傳送資料,主機A若正確接收資料仍需要傳送確認。      3)在主機B向主機A的資料傳送結束後,其應用程序就通知TCP釋放連線。主機B發出的連線釋放報文段必須將終止位元置為1,並使其序號w等於前面已經傳送過的資料的最後一個位元組的序號加 1,還必須重複上次已傳送過的ACK=u+1。      4)主機A對主機B的連線釋放報文段發出確認,將ACK置為1,ACK=w+1, seq=u+1。這樣才把從B到A的反方向連線釋放掉,主機A的TCP再向其應用程序報告,整個連線已經全部釋放。  

2. 雙方主動關閉的TCP連線釋放流程

     與可以雙方同時建立TCP傳輸連線一樣,TCP傳輸連線關閉也可以由雙方同時主動進行(正常情況下都是由一方傳送第一個FIN資料段進行主動連線關閉,另一方被動接受連線關閉),如圖10-41所示。具體描述如下:


  同時主動關閉TCP連線的流程

        當兩端對應的網路應用層程序同時呼叫CLOSE原語,傳送FIN資料段執行關閉命令時,兩端均從ESTABLISHED狀態轉變為FIN WAIT 1狀態。任意一方收到對端發來的FIN資料段後,其狀態均由FIN WAIT 1轉變到CLOSING狀態,併發送最後的ACK資料段。當收到最後的ACK資料段後,狀態轉變化TIME_WAIT,在等待2MSL後進入到CLOSED狀態,最終釋放整個TCP傳輸連線。 3.注意的問題
  • 三次握手建立連線時,傳送方再次傳送確認的必要性
    • 主要是為了防止已失效的連線請求報文段突然又傳到了B,因而產生錯誤。假定出現一種異常情況,即A發出的第一個連線請求報文段並沒有丟失,而是在某些網路結點長時間滯留了,一直延遲到連線釋放以後的某個時間才到達B,本來這是一個早已失效的報文段。但B收到此失效的連線請求報文段後,就誤認為是A又發出一次新的連線請求,於是就向A發出確認報文段,同意建立連線。假定不採用三次握手,那麼只要B發出確認,新的連線就建立了,這樣一直等待A發來資料,B的許多資源就這樣白白浪費了。
    • 三次握手是連線兩端正確同步的充要條件,因為TCP建立在不可靠的分組傳輸服務之上,報文可能丟失、延遲、重複和亂序,因此協議必須使用超時和重傳機制。如果重傳的連線請求和原先的連線請求在連線正在建立時到達,或者當一個連線已經建立、使用和結束之後,某個延遲的連線請求才到達,就會出現問題。採用三次握手協議就可以解決這些問題。如客戶端傳送的ACK資料段就是為了避免因網路延遲而導致的重複連線,因為這時客戶端就可通過檢查ACK資料段中的確認號就可得知該連線請求是否已失效。
  • 四次揮手釋放連線時,等待2MSL的意義
    • 1)可靠地實現TCP全雙工連線的終止        第一,為了保證A傳送的最有一個ACK報文段能夠到達B。這個ACK報文段有可能丟失,因而使處在LAST-ACK狀態的B收不到對已傳送的FIN和ACK報文段的確認。B會超時重傳這個FIN和ACK報文段,而A就能在2MSL時間內收到這個重傳的ACK+FIN報文段。接著A重傳一次確認。在進行關閉連線四路握手協議時,最後的ACK是由主動關閉端發出的,如果這個最終的ACK丟失,伺服器將重發最終的FIN,因此客戶端必須維護狀態資訊允 許它重發最終的ACK。如果不維持這個狀態資訊,那麼客戶端將響應RST分節,伺服器將此分節解釋成一個錯誤(在java中會丟擲connection reset的SocketException)。因而,要實現TCP全雙工連線的正常終止,必須處理終止序列四個分節中任何一個分節的丟失情況,主動關閉 的客戶端必須維持狀態資訊進入TIME_WAIT狀態。

    • 2)允許老的重複分節在網路中消逝  
          TCP分節可能由於路由器異常而“迷途”,在迷途期間,TCP傳送端可能因確認超時而重發這個分節,迷途的分節在路由器修復後也會被送到最終目的地,這個 原來的迷途分節就稱為lost duplicate。在關閉一個TCP連線後,馬上又重新建立起一個相同的IP地址和埠之間的TCP連線,後一個連線被稱為前一個連線的化身 (incarnation),那麼有可能出現這種情況,前一個連線的迷途重複分組在前一個連線終止後出現,從而被誤解成從屬於新的化身。為了避免這個情 況,TCP不允許處於TIME_WAIT狀態的連線啟動一個新的化身,因為TIME_WAIT狀態持續2MSL,就可以保證當成功建立一個TCP連線的時 候,來自連線先前化身的重複分組已經在網路中消逝。

    • TIME_WAIT的優缺點:

      短時間的多次請求可能會導致伺服器上存在很多的TIME_WAIT,那麼導致埠被用盡,無法繼續訪問應用程式。四次握手關閉也不是必須的,也可以通過套接字選項設定不需要關注TIME_WAIT狀態。

4.TCP的有限狀態機      連線的建立和釋放所要求的步驟可以用一個有限狀態機來表達,該狀態機有11種狀態。每一種狀態中都存在一些合法的事件,當合法事件發生的時候,可能需要採取某個動作。當其他事件發生的時候,則報告一個錯誤。

狀 態

描 述

CLOSED

關閉狀態,沒有連線活動或正在進行

LISTEN

監聽狀態,伺服器正在等待連線進入

SYN RCVD

收到一個連線請求,尚未確認

SYN SENT

已經發出連線請求,等待確認

ESTABLISHED

連線建立,正常資料傳輸狀態

FIN WAIT 1

(主動關閉)已經發送關閉請求,等待確認

FIN WAIT 2

(主動關閉)收到對方關閉確認,等待對方關閉請求

TIMED WAIT

完成雙向關閉,等待所有分組死掉

CLOSING

雙方同時嘗試關閉,等待對方確認

CLOSE WAIT

(被動關閉)收到對方關閉請求,已經確認

LAST ACK

(被動關閉)等待最後一個關閉確認,並等待所有分組死掉

TCP建立與釋放的變遷如圖所示:

  • 客戶程序變遷的過程(粗實線)
    • 連線建立:設一個主機的客戶程序發起連線請求(主動開啟),這時本地TCP實體就建立傳輸控制快(TCB),傳送一個SYN為1的報文,進入SYN_SENT狀態。當收到來自程序的SYN和ACK時,TCP就傳送出三次握手中的最後一個ACK,進而進入連線已經建立的狀態ESTABLISHED。
    • 連線釋放:設執行客戶程序主機本地TCP實體傳送一個FIN置為1的報文,等待著確認ACK的到達,此時狀態變為FIN_WAIT_1。當執行客戶程序主機收到確認ACK時,則一個方向的連線已經關閉。狀態變成FIN_WAIT_2。當執行客戶程序的主機收到執行伺服器程序的主機發送的FIN置為1的報文後,應響應確認ACK時,這是另一個連線關閉。但此時TCP還要等待一段時間後才刪除原來建立的連線記錄。返回到初始的CLOSED狀態,這是為了保證原來連線上的所有分組都從網路中消失了。
  • 伺服器程序變遷的過程(粗虛線)
    • 連線建立:伺服器程序發出被動開啟,進入監聽狀態LISTEN。當收到SYN置為1的連線請求報文後,傳送確認ACK,並且報文中的SYN也置為1,然後進入SYN_RCVD狀態。在收到三次握手最後一個確認ACK時,就轉為ESTABLISHED狀態。
    • 連線釋放:當客戶程序的資料已經傳送完畢。就發出FIN置為1的報文給伺服器程序,進入CLOSE_WAIT狀態。伺服器程序傳送FIN報文段給客戶程序,狀態變為LAST_ACK狀態。當收到客戶程序的ACK時,伺服器程序就釋放連線。刪除連線記錄。回到原來的CLOSED狀態。