系列TCP/IP協議-TCP創建與終止鏈接(012)

1、引言

TCP是一個面向鏈接的協議。不管哪一方向另外一方發送數據以前,都必須先在雙方之間創建一條鏈接。鏈接建立與終止的狀態變化圖以下: 算法

圖1.tcp創建鏈接與終止鏈接狀態轉換圖

2、三次握手創建鏈接

圖2.tcp創建鏈接三次握手
過程以下:

  • 客戶端發送一個SYN數據包指明客戶端打算鏈接服務器的端口,初始化序號(ISN)爲m。
  • 服務器發回包含服務器的ISN做爲應答(值爲n)。同時,將確認序號設置成客戶端ISN+1(m+1)來做爲對客戶端SYN的確認。
  • 客戶端發送一個ACK數據包,ack=n+1,做爲對服務器的SYN的確認。

1.爲何是三次握手,而不是兩次

網絡是不可靠的,數據包是可能丟失的。假設沒有第三次確認,客戶端向服務端發送了 SYN,請求創建鏈接。因爲延遲,服務端沒有及時收到這個包。因而客戶端從新發送一個 SYN 包。回憶一下介紹 TCP 首部時提到的序列號,這兩個包的序列號顯然是相同的。假設服務端接收到了第二個 SYN 包,創建了通訊,一段時間後通訊結束,鏈接被關閉。這時候最初被髮送的 SYN 包剛剛抵達服務端,服務端又會發送一次 ACK 確認。因爲兩次握手就創建了鏈接,此時的服務端就會創建一個新的鏈接,然而客戶端以爲本身並無請求創建鏈接,因此就不會向服務端發送數據。從而致使服務端創建了一個空的鏈接,白白浪費資源。   TCP是雙通道,須要雙向肯定。只有兩次握手,客戶端知道了服務器收到了,服務器不知道客戶端收到了,聯想打電話。通信系統中的占拜庭將軍問題。服務器

2.最大報文段長度

最大報文段長度(MSS)表示TCP傳往另外一端的最大塊數據的長度。當一個鏈接創建時,鏈接的雙方都要通告各自的MSS。在三次握手的時候SYN的TCP首部中的可選字段肯定。以太網的默認長度爲1460。微信

3.

3、四次握手關閉鏈接(正常狀態)

創建一個鏈接須要三次握手,而終止一個鏈接要通過4次握手。這由TCP的半關閉(half-close)形成的。一個TCP鏈接是全雙工(即數據在兩個方向上能同時傳遞),所以每一個方向必須單獨地進行關閉。 網絡

圖3.四次握手關閉鏈接

  • 主動方想要關閉鏈接,發送FIN包給被動方,序號爲m
  • 被動方接收到主動方發送的FIN包,知道了對方要關閉鏈接,發送ACK確認包,序號m+1。主動方鏈接關閉。
  • 等待片刻(處於半關閉狀態),在此期間(fin_wait2,close_wait)。被動方發送最後的數據,主動方接收最後的數據。
  • 被動方確認要關閉鏈接,發送FIN包。序號n。
  • 主動方等待片刻(接收網絡中,還未到達的數據包),發送ACK確認包。序號n+1。到此鏈接關閉。

1.TCP的半關閉狀態

TCP提供了鏈接的一端在結束它的發送後還能接收來自另外一端數據的能力。如主動方處於fin_wait2狀態。併發

2.TIME_WAIT狀態

TIME_WAIT狀態也稱爲2MSL等待狀態。每一個具體TCP實現必須選擇一個報文段最大生存時間MSL( Maximum Segment Lifetime)。它是任何報文段被丟棄前在網絡內的最長時間。由於TCP報文段以IP數據報在網絡內傳輸,而IP數據報則有限制其生存時間的TTL字段。在實際應用中,對 I P數據報TTL的限制是基於跳數,而不是定時器。   在處於2MSL等待狀態的socket(客戶端IP與端口,服務器IP與端口)不能再被使用。但在實際的使用中,容許一個新的鏈接請求到達仍處於time_wait狀態的鏈接,只要新的序號大於該鏈接的前一個鏈接的最後序號。socket

4、正常狀態抓包

下面是一次完整的tcp創建鏈接,發送數據,關閉鏈接過程 tcp

圖4.tcp一次完整請求

該過程爲,3次握手創建鏈接,一次數據發送,4次握手關閉鏈接操作系統

5、異常狀況

出現異常的時候,服務器一般經過復位報文來通告,復位報文爲tcp數據包類型設置爲rst。設計

1.鏈接超時或到達不存在的端口/服務器

當服務器端沒有開或網絡問題,會出現鏈接超時的狀況。抓包以下: code

圖5.鏈接超時
客戶端嘗試3三次來鏈接,有時候服務器端會發送rst數據包。

2.異常終止一個鏈接

在TCP通信中。若是通信雙方應爲某種緣由(如忽然斷電等)關閉鏈接時候一方(如A)沒有發送fin數據包。另外一端(如B)不知道對方已經關閉了鏈接。再次發送數據的時候,異常關閉的一方,可能會返回一個rst數據包。通知異常關閉。若是一方已經關閉或異常終止鏈接而另外一方卻還不知道,咱們將這樣的TCP鏈接稱爲半打開(Half Open)的。

3.同時打開

兩個應用程序同時彼此執行主動打開的狀況是可能的。每一方必須發送一個SYN,且這些SYN必須傳遞給對方。這須要每一方使用一個對方熟知的端口做爲本地端口。同時打開的狀態遷移圖不一樣於正常狀態的三次握手,該狀況下須要進行4次握手。如圖:

圖6.同時打開,4次握手創建鏈接

4.同時關閉

咱們在之前討論過一方(一般但不老是客戶方)發送第一個FIN執行主動關閉。雙方都執行主動關閉也是可能的,TCP協議也容許這樣的同時關閉(simultaneous close)。在同時關閉的時候,雙方都進入time_wait狀態,如圖:

圖7.TCP同時關閉鏈接狀態轉換圖

六.TCP服務器設計

大多數的TCP服務器進程是併發的。當一個新的鏈接請求到達服務器時,服務器接受這個請求,並調用一個新進程來處理這個新的客戶請求。

1. 接入鏈接請求隊列

一個併發服務器調用一個新的進程來處理每一個客戶請求,所以處於被動鏈接請求的服務器應該始終準備處理下一個呼入的鏈接請求。那正是使用併發服務器的根本緣由。但仍有可能出現當服務器在建立一個新的進程時,或操做系統正忙於處理優先級更高的進程時,到達多個鏈接請求。當服務器正處於忙時,TCP是如何處理這些呼入的鏈接請求?TCP有這樣一個隊列來臨時存放這些鏈接-接入鏈接請求隊列。處理方式以下:

  • 正等待鏈接請求的一端有一個固定長度的鏈接隊列,該隊列中的鏈接已被TCP接受(即三次握手已經完成),但尚未被應用層所接受。注意區分TCP接受一個鏈接是將其放入這個隊列,而應用層接受鏈接是將其從該隊列中移出。
  • 應用層將指明該隊列的最大長度,這個值一般稱爲積壓值 (backlog)。
  • 當一個鏈接請求(SYN)到達時, TCP使用一個算法,根據當前鏈接隊列中的鏈接數來肯定是否接收這個鏈接。積壓值說明的是TCP監聽的端口已被TCP接受而等待應用層接受的最大鏈接數。
  • 若是對於新的鏈接請求,該TCP監聽的端口的鏈接隊列中還有空間,TCP模塊將對SYN進行確認並完成鏈接的創建。此時,應用層不必定知道該新的鏈接,若是對方發送數據,這些數據將放入緩衝隊列中。
  • 若是對於新的鏈接請求,鏈接隊列中已沒有空間,TCP將不理會收到的SYN。也不發回任何報文段(即不發回 RST)。若是應用層不能及時接受已被TCP接受的鏈接,這些鏈接可能佔滿整個鏈接隊列,客戶的主動打開最終將超時。

都看到這裏了,要不要掃二維碼關注一下微信公衆號林灣村龍貓

微信公衆號rudy_tan_home
相關文章
相關標籤/搜索