1. 程式人生 > >深入理解TCP/IP協議-TCP建立與終止連線

深入理解TCP/IP協議-TCP建立與終止連線

轉載自  深入理解TCP/IP協議-TCP建立與終止連線

 

一、引言

  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。

 

三、四次握手關閉連線(正常狀態)

  建立一個連線需要三次握手,而終止一個連線要經過 4 次握手。這由 TCP 的半關閉 (half-close) 造成的。一個 TCP 連線是全雙工(即資料在兩個方向上能同時傳遞),因此每個方向必須單獨地進行關閉。

  • 主動方想要關閉連線,傳送 FIN 包給被動方,序號為 m

  • 被動方接收到主動方傳送的 FIN 包,知道了對方要關閉連線,傳送 ACK 確認包,序號 m+1。主動方連線關閉。

  • 等待片刻(處於半關閉狀態),在此期間(finwait2,closewait)。被動方傳送最後的資料,主動方接收最後的資料。

  • 被動方確認要關閉連線,傳送 FIN 包。序號 n。

  • 主動方等待片刻(接收網路中,還未到達的資料包),傳送 ACK 確認包。序號 n+1。到此連線關閉。

1.TCP 的半關閉狀態

  TCP 提供了連線的一端在結束它的傳送後還能接收來自另一端資料的能力。如主動方處於 fin_wait2 狀態。

2.TIME_WAIT 狀態

  TIMEWAIT 狀態也稱為 2MSL 等待狀態。每個具體 TCP 實現必須選擇一個報文段最大生存時間 MSL( Maximum Segment Lifetime)。它是任何報文段被丟棄前在網路內的最長時間。因為 TCP 報文段以 IP 資料報在網路內傳輸,而 IP 資料報則有限制其生存時間的 TTL 欄位。在實際應用中,對 I P 資料報 TTL 的限制是基於跳數,而不是定時器。   在處於 2MSL 等待狀態的 socket(客戶端 IP 與埠,伺服器 IP 與埠) 不能再被使用。但在實際的使用中,允許一個新的連線請求到達仍處於 timewait 狀態的連線,只要新的序號大於該連線的前一個連線的最後序號。

 

四、正常狀態抓包

下面是一次完整的 tcp 建立連線,傳送資料,關閉連線過程

該過程為,3 次握手建立連線,一次資料傳送,4 次握手關閉連線

 

 

五、異常情況

出現異常的時候,伺服器通常通過復位報文來通告,復位報文為 tcp 資料包型別設定為 rst。

1. 連線超時或到達不存在的埠 / 伺服器

當伺服器端沒有開或網路問題,會出現連線超時的情況。抓包如下:

客戶端嘗試 3 三次來連線,有時候伺服器端會發送 rst 資料包。

2. 異常終止一個連線

  在 TCP 通訊中。如果通訊雙方應為某種原因(如突然斷電等)關閉連線時候一方(如 A)沒有傳送 fin 資料包。另一端 (如 B) 不知道對方已經關閉了連線。再次傳送資料的時候,異常關閉的一方,可能會返回一個 rst 資料包。通知異常關閉。如果一方已經關閉或異常終止連線而另一方卻還不知道,我們將這樣的 TCP 連線稱為半開啟 (Half Open) 的。

3. 同時開啟

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

4. 同時關閉

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

 

六. TCP 伺服器設計

  大多數的 TCP 伺服器程序是併發的。當一個新的連線請求到達伺服器時,伺服器接受這個請求,並呼叫一個新程序來處理這個新的客戶請求。

1. 接入連線請求佇列

  一個併發伺服器呼叫一個新的程序來處理每個客戶請求,因此處於被動連線請求的伺服器應該始終準備處理下一個呼入的連線請求。那正是使用併發伺服器的根本原因。但仍有可能出現當伺服器在建立一個新的程序時,或作業系統正忙於處理優先順序更高的程序時,到達多個連線請求。當伺服器正處於忙時,TCP 是如何處理這些呼入的連線請求?TCP 有這樣一個佇列來臨時存放這些連線 - 接入連線請求佇列。處理方式如下:

  • 正等待連線請求的一端有一個固定長度的連線佇列,該佇列中的連線已被 TCP 接受(即三次握手已經完成),但還沒有被應用層所接受。注意區分 TCP 接受一個連線是將其放入這個佇列,而應用層接受連線是將其從該佇列中移出。

  • 應用層將指明該佇列的最大長度,這個值通常稱為積壓值 (backlog)。

  • 當一個連線請求(SYN)到達時, TCP 使用一個演算法,根據當前連線佇列中的連線數來確定是否接收這個連線。積壓值說明的是 TCP 監聽的埠已被 TCP 接受而等待應用層接受的最大連線數。

  • 如果對於新的連線請求,該 TCP 監聽的埠的連線佇列中還有空間,TCP 模組將對 SYN 進行確認並完成連線的建立。此時,應用層不一定知道該新的連線,如果對方傳送資料,這些資料將放入緩衝佇列中。

  • 如果對於新的連線請求,連線佇列中已沒有空間,TCP 將不理會收到的 SYN。也不發回任何報文段(即不發回 RST)。如果應用層不能及時接受已被 TCP 接受的連線,這些連線可能佔滿整個連線佇列,客戶的主動開啟最終將超時。