TCP 三次握手 四次揮手 的狀態轉移(摘抄)

TCP 狀態機

 TCP 協議的操作可以使用一個具有 11 種狀態的有限狀態機( Finite State Machine )來表示,圖 3-12 描述了 TCP 的有限狀態機,圖中的圓角矩形表示狀態,箭頭表示狀態之間的轉換,各狀態的描述如表 3-2 所示。圖中用粗線表示客戶端主動和被動的服務器端建立連接的正常過程:客戶端的狀態變遷用粗實線,服務器端的狀態變遷用粗虛線。細線用於不常見的序列,如 復位、同時打開、同時關閉等。圖中的每條狀態變換線上均標有“事件/動作”:事件是指用戶執行了系統調用( CONNECT 、 LISTEN 、 SEND 或 CLOSE )、收到一個報文段( SYN 、 FIN 、 ACK 或 RST )、或者是出現了超過兩倍最大的分組生命期的情況;動作是指發送一個報文段( SYN 、 FIN 或 ACK )或什麼也沒有(用“-”表示)。

每 個連接均開始於 CLOSED 狀態。當一方執行了被動的連接原語( LISTEN )或主動的連接原語( CONNECT )時,它便會脫離 CLOSED 狀態。如果此時另一方執行了相對應的連接原語,連接便建立了,並且狀態變爲 ESTABLISHED 。任何一方均可以首先請求釋放連接,當連接被釋放後,狀態又回到了 CLOSED 。

表 3-2 TCP 狀態表

 

狀 態

描 述

CLOSED

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

LISTEN

監聽狀態,服務器正在等待連接進入

SYN RCVD

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

SYN SENT

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

ESTABLISHED

連接建立,正常數據傳輸狀態

FIN WAIT 1

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

FIN WAIT 2

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

TIMED WAIT

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

CLOSING

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

CLOSE WAIT

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

LAST ACK

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

 

1. 正常狀態轉換

   我們用圖 3-13 來顯示在正常的 TCP 連接的建立與終止過程中,客戶與服務器所經歷的不同狀態。讀者可以對照圖 3-12 來閱讀,使用圖 3-12 的狀態圖來跟蹤圖 3-13 的狀態變化過程,以便明白每個狀態的變化:

  • 服務器端首先執行 LISTEN 原語進入被動打開狀態( LISTEN ),等待客戶端連接;
  • 當客戶端的一個應用程序發出 CONNECT 命令後,本地的 TCP 實體爲其創建一個連接記錄並標記爲 SYN SENT 狀態,然後給服務器發送一個 SYN 報文段;
  • 服務器收到一個 SYN 報文段,其 TCP 實體給客戶端發送確認 ACK 報文段同時發送一個 SYN 信號,進入 SYN RCVD 狀態;
  • 客戶端收到 SYN + ACK 報文段,其 TCP 實體給服務器端發送出三次握手的最後一個 ACK 報文段,並轉換爲 ESTABLISHED 狀態;
  • 服務器端收到確認的 ACK 報文段,完成了三次握手,於是也進入 ESTABLISHED 狀態。

  在此狀態下,雙方可以自由傳輸數據。當一個應用程序完成數據傳輸任務後,它需要關閉 TCP 連接。假設仍由客戶端發起主動關閉連接。

  • 客戶端執行 CLOSE 原語,本地的 TCP 實體發送一個 FIN 報文段並等待響應的確認(進入狀態 FIN WAIT 1 );
  • 服務器收到一個 FIN 報文段,它確認客戶端的請求發回一個 ACK 報文段,進入 CLOSE WAIT 狀態;
  • 客戶端收到確認 ACK 報文段,就轉移到 FIN WAIT 2 狀態,此時連接在一個方向上就斷開了;
  • 服務器端應用得到通告後,也執行 CLOSE 原語關閉另一個方向的連接,其本地 TCP 實體向客戶端發送一個 FIN 報文段,並進入 LAST ACK 狀態,等待最後一個 ACK 確認報文段;
  • 客戶端收到 FIN 報文段並確認,進入 TIMED WAIT 狀態,此時雙方連接均已經斷開,但 TCP 要等待一個 2 倍報文段最大生存時間 MSL ( Maximum Segment Lifetime ),確保該連接的所有分組全部消失,以防止出現確認丟失的情況。當定時器超時後, TCP 刪除該連接記錄,返回到初始狀態( CLOSED )。
  • 服務器收到最後一個確認 ACK 報文段,其 TCP 實體便釋放該連接,並刪除連接記錄,返回到初始狀態( CLOSED )。


image

圖 1 TCP 有限狀態機





  TCP 是一個面向連接的協議,無論哪一方向另一方發送數據之前,都必須先在雙方之間建立一條連接。本節將詳細討論一個TCP 連接是如何建立的以及通信結束後是如何終止的。

建立一個 TCP 連接

  TCP使用三次握手 ( three-way handshake ) 協議來建立連接,圖 3-10 描述了三次握手的報文序列。這三次握手爲:

  • 請求端(通常稱爲客戶)發送一個 SYN 報文段( SYN 爲 1 )指明客戶打算連接的服務器的端口,以及初始順序號( ISN )。

  • 服務器發回包含服務器的初始順序號的 SYN 報文段( SYN 爲 1 )作爲應答。同時,將確認號設置爲客戶的 ISN 加 1 以對客戶的 SYN 報文段進行確認( ACK 也爲 1 )。

  • 客戶必須將確認號設置爲服務器的 ISN 加 1 以對服務器的 SYN 報文段進行確認( ACK 爲 1 ),該報文通知目的主機雙方已完成連接建立。

TCP 狀態機 - wdqfirst - Dengqiang Wang  Blog

  發送第一個 SYN 的一端將執行主動打開( active open ),接收這個 SYN 併發回下一個 SYN 的另一端執行被動打開( passive open )。另外, TCP 的握手協議被精心設計爲可以處理同時打開( simultaneous open ),對於同時打開它僅建立一條連接而不是兩條連接。因此,連接可以由任一方或雙方發起,一旦連接建立,數據就可以雙向對等地流動,而沒有所謂的主從關係。

  三次握手協議是連接兩端正確同步的充要條件。因爲 TCP 建立在不可靠的分組傳輸服務之上,報文可能丟失、延遲、重複和亂序,因此協議必須使用超時和重傳機制。如果重傳的連接請求和原先的連接請求在連接正在建立 時到達,或者當一個連接已經建立、使用和結束之後,某個延遲的連接請求才到達,就會出現問題。採用三次握手協議(加上這樣的規則:在連接建立之後 TCP 就不再理睬又一次的連接請求)就可以解決這些問題。

  三次握手協議可以完成兩個重要功能:它確保連接雙方做好傳輸準備,並使雙方統一了初始 順序號。初始順序號是在握手期間傳輸順序號並獲得確認:當一端爲建立連接而發送它的 SYN 時,它爲連接選擇一個初始順序號;每個報文段都包括了順序號字段和確認號字段,這使得兩臺機器僅僅使用三個握手報文就能協商好各自的數據流的順序號。一般 來說, ISN 隨時間而變化,因此每個連接都將具有不同的 ISN 。

關閉一個 TCP 連接

  TCP 連接建立起來後,就可以在兩個方向傳送數據流。當 TCP 的應用進程再沒有數據需要發送時,就發關閉命令。 TCP 通過發送控制位 FIN=1 的數據片來關閉本方數據流,但還可以繼續接收數據,直到對方關閉那個方向的數據流,連接就關閉。

  TCP 協議使用修改的三次握手協議來關閉連接, 如圖 3-11 所示,即終止一個連接要經過 4 次握手。這是因爲 TCP 的半關閉( half-close )造成的。由於一個 TCP 連接是全雙工(即數據在兩個方向上能同時傳遞),因此每個方向必須單獨地進行關閉。關閉的原則就是當一方完成它的數據發送任務後就能發送一個 FIN 來終止這個方向連接。當一端收到一個 FIN ,它必須通知應用層另一端已經終止了那個方向的數據傳送。發送 FIN 通常是應用層進行關閉的結果。

TCP 狀態機 - wdqfirst - Dengqiang Wang  Blog

  從一方的 TCP 來說,連接的關閉有三種情況:

  ? 本方啓動關閉

  收到本方應用進程的關閉命令後, TCP 在發送完尚未處理的報文段後,發 FIN = 1 的報文段給對方,且 TCP 不再受理本方應用進程的數據發送。在 FIN 以前發送的數據字節,包括 FIN ,都需要對方確認,否則要重傳。注意 FIN 也佔一個順序號。一旦收到對方對 FIN 的確認以及對方的 FIN 報文段,本方 TCP 就對該 FIN 進行確認,在等待一段時間,然後關閉連接。等待是爲了防止本方的確認報文丟失,避免對方的重傳報文干擾新的連接。

  ? 對方啓動關閉

  當 TCP 收到對方發來的 FIN 報文時,發 ACK 確認此 FIN 報文,並通知應用進程連接正在關閉。應用進程將以關閉命令響 應。 TCP 在發送完尚未處理的報文段後,發一個 FIN 報文給對方 TCP ,然後等待對方對 FIN 的確認,收到確認後關閉連接。若對方的確認未及時到達,在等待一段時間後也關閉連接。

  ? 雙方同時啓動關閉

  連接雙方的應用進程同時發關閉命令,則雙方 TCP 在發送完尚未處理的報文段後,發送 FIN 報文。各方 TCP 在 FIN 前所發報文都得到確認後,發 ACK 確認它收到的 FIN 。各方在收到對方對 FIN 的確認後,同樣等待一段時間再關閉連接。這稱之爲同時關閉( simultaneous close )。

TCP 狀態機

  TCP 協議的操作可以使用一個具有 11 種狀態的有限狀態機( Finite State Machine )來表示,圖 3-12 描述了 TCP 的有限狀態機,圖中的圓角矩形表示狀態,箭頭表示狀態之間的轉換,各狀態的描述如表 3-2 所示。圖中用粗線表示客戶端主動和被動的服務器端建立連接的正常過程:客戶端的狀態變遷用粗實線,服務器端的狀態變遷用粗虛線。細線用於不常見的序列,如 復位、同時打開、同時關閉等。圖中的每條狀態變換線上均標有“事件/動作”:事件是指用戶執行了系統調用( CONNECT 、 LISTEN 、 SEND 或 CLOSE )、收到一個報文段( SYN 、 FIN 、 ACK 或 RST )、或者是出現了超過兩倍最大的分組生命期的情況;動作是指發送一個報文段( SYN 、 FIN 或 ACK )或什麼也沒有(用“-”表示)。

TCP 狀態機 - wdqfirst - Dengqiang Wang  Blog

圖 3-12 TCP 有限狀態機。粗實線表示客戶的正常路徑;
粗虛線表示服務器的正常路徑;細線表示不常見的事件。

  每個連接均開始於 CLOSED 狀態。當一方執行了被動的連接原語( LISTEN )或主動的連接原語( CONNECT )時,它便會脫離 CLOSED 狀態。如果此時另一方執行了相對應的連接原語,連接便建立了,並且狀態變爲 ESTABLISHED 。任何一方均可以首先請求釋放連接,當連接被釋放後,狀態又回到了 CLOSED 。

表 3-2 TCP 狀態表

狀 態

描 述

CLOSED

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

LISTEN

監聽狀態,服務器正在等待連接進入

SYN RCVD

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

SYN SENT

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

ESTABLISHED

連接建立,正常數據傳輸狀態

FIN WAIT 1

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

FIN WAIT 2

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

TIMED WAIT

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

CLOSING

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

CLOSE WAIT

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

LAST ACK

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

1. 正常狀態轉換

  我們用圖 3-13 來顯示在正常的 TCP 連接的建立與終止過程中,客戶與服務器所經歷的不同狀態。讀者可以對照圖 3-12 來閱讀,使用圖 3-12 的狀態圖來跟蹤圖 3-13 的狀態變化過程,以便明白每個狀態的變化:

  • 服務器端首先執行 LISTEN 原語進入被動打開狀態( LISTEN ),等待客戶端連接;

  • 當客戶端的一個應用程序發出 CONNECT 命令後,本地的 TCP 實體爲其創建一個連接記錄並標記爲 SYN SENT 狀態,然後給服務器發送一個 SYN 報文段;

  • 服務器收到一個 SYN 報文段,其 TCP 實體給客戶端發送確認 ACK 報文段同時發送一個 SYN 信號,進入 SYN RCVD 狀態;

  • 客戶端收到 SYN + ACK 報文段,其 TCP 實體給服務器端發送出三次握手的最後一個 ACK 報文段,並轉換爲 ESTABLISHED 狀態;

  • 服務器端收到確認的 ACK 報文段,完成了三次握手,於是也進入 ESTABLISHED 狀態。

   在此狀態下,雙方可以自由傳輸數據。當一個應用程序完成數據傳輸任務後,它需要關閉 TCP 連接。假設仍由客戶端發起主動關閉連接。

  • 客戶端執行 CLOSE 原語,本地的 TCP 實體發送一個 FIN 報文段並等待響應的確認(進入狀態 FIN WAIT 1 );

  • 服務器收到一個 FIN 報文段,它確認客戶端的請求發回一個 ACK 報文段,進入 CLOSE WAIT 狀態;

  • 客戶端收到確認 ACK 報文段,就轉移到 FIN WAIT 2 狀態,此時連接在一個方向上就斷開了;

  • 服務器端應用得到通告後,也執行 CLOSE 原語關閉另一個方向的連接,其本地 TCP 實體向客戶端發送一個 FIN 報文段,並進入 LAST ACK 狀態,等待最後一個 ACK 確認報文段;

  • 客戶端收到 FIN 報文段並確認,進入 TIMED WAIT 狀態,此時雙方連接均已經斷開,但 TCP 要等待一個 2 倍報文段最大生存時間 MSL ( Maximum Segment Lifetime ),確保該連接的所有分組全部消失,以防止出現確認丟失的情況。當定時器超時後, TCP 刪除該連接記錄,返回到初始狀態( CLOSED )。

  • 服務器收到最後一個確認 ACK 報文段,其 TCP 實體便釋放該連接,並刪除連接記錄,返回到初始狀態( CLOSED )。

TCP 狀態機 - wdqfirst - Dengqiang Wang  Blog

2. 同時打開:

  儘管發生的可能性極小,兩個應用程序同時彼此執行主動打開的情況還是可能的。每一方必 鬚髮送一個 SYN ,且這些 SYN 必須傳遞給對方。這需要每一方使用一個對方周知的端口作爲本地端口。例如,主機 A 中的一個應用程序使用本地端口 7777 ,並與主機 B 的端口 8888 執行主動打開。主機 B 中的應用程序則使用本地端口 8888 ,並與主機 A 的端口 7777 執行主動打開。 TCP 是特意設計爲了可以處理同時打開,對於同時打開它僅建立一條連接而不是兩條連接(其他的協議族,最突出的是 OSI 傳輸層,在這種情況下將建立兩條連接而不是一條連接)。

  當出現同時打開的情況時,狀態變遷與圖 3-13 所示的不同。兩端幾乎在同時發送 SYN ,並進入 SYN_SENT 狀態。當每一端收到 SYN 時,狀態變爲 SYN_RCVD ,同時它們都再發 SYN 並對收到的 SYN 進行確認。當雙方都收到 SYN 及相應的 ACK 時,狀態都變遷爲 ESTABLISHED 。圖 3-14 顯示了這些狀態變遷過程。

TCP 狀態機 - wdqfirst - Dengqiang Wang  Blog

圖 3-14 同時打開期間報文段的交換

 

  一個同時打開的連接需要交換 4 個報文段,比正常的三次握手多一個。此外,要注意的是我們沒有將任何一端稱爲客戶或服務器,因爲每一端既是客戶又是服務器。

3. 同時關閉:

  正常情況下都是由一方(通常但不總是客戶方)發送第一個 FIN 執行主動關閉,但雙方都執行主動關閉也是可能的, TCP 協議也允許這樣的同時關閉。

  在圖 3-12 中,當兩端應用層同時發出關閉命令時,兩端均從 ESTABLISHED 變爲 FIN_WAIT_1 。這將導致雙方各發送一個 FIN ,兩個 FIN 經過網絡傳送後分別到達另一端。收到 FIN 後,狀態由 FIN_WAIT_1 變遷到 CLOSING ,併發送最後的 ACK 。當收到最後的 ACK 時,狀態變化爲 TIME_WAIT 。圖 3-15 總結了這些狀態的變化,從圖中可以看出同時關閉與正常關閉使用的報文段交換數目相同。

TCP 狀態機 - wdqfirst - Dengqiang Wang  Blog

圖 3-15 同時關閉期間的報文段交換

4. 其它情況:

  • 服務方打開:從 LISTEN 到 SYN_SENT 的變遷是正確的,它由服務器端主動發出 SYN 報文段,但 Berkeley 版的 TCP 軟件並不支持它。

  • 重置連接(復位):只有當 SYN_RCVD 狀態是從 LISTEN 狀態(正常情況)進入,而不是從 SYN_SENT 狀態(同時打開)進入時,從 SYN_RCVD 回到 LISTEN 的狀態變遷纔是有效的。這意味着如果我們執行被動打開(進入 LISTEN ),收到一個 SYN ,發送一個帶 ACK 的 SYN (進入 SYN_RCVD ),然後收到一個 RST ,而不是一個 ACK ,便又回到 LISTEN 狀態並等待另一個連接請求的到來。

  • 快速關閉:在主動關閉後的 FIN_WAIT_1 狀態,如果收到的報文段不僅是 ACK ,而且還包括對方的 FIN 信號,則直接進入 TIME_WAIT 狀態,給對方發送 ACK 報文段,然後等待超時。

  另外, TIME_WAIT 狀態的等待超時需要再詳細解釋一下,因爲它直接影響到網絡應用程序的表現。

  每個具體 TCP 實現必須選擇一個報文段最大生存時間 MSL ( Maximum Segment Lifetime ),它是任何報文段被丟棄前在網絡內的最長時間。我們知道這個時間是有限的,因爲 TCP 報文段以 IP 數據報在網絡內傳輸,而 IP 數據報有限制其生存時間的 TTL 字段。 RFC 793 [Postel 1981c ] 指出 MSL 爲 2 分鐘。然而,實現中的常用值是 30 秒、 1 分鐘、或 2 分鐘。

  對一個具體實現所給定的 MSL 值,處理的原則是:當 TCP 執行一個主動關閉,併發回最後一個 ACK ,該連接必須在 TIME_WAIT 狀態停留的時間爲 2 倍的 MSL ,因此 TIME_WAIT 狀態也稱爲 2MSL 等待狀態。在這段時間內,如果最後的 ACK 丟失,對方會超時並重發最後的 FIN ,這樣本地 TCP 可以再次發送 ACK 報文段(這也是它唯一可以發送的報文,並重置 2MSL 定時器)。

  這種 2MSL 等待的另一個結果是這個 TCP 連接在 2MSL 等待期間,定義這個連接的套接字( socket ,客戶的 IP 地址和端口號,服務器的 IP 地址和端口號)不能再被使用。這個連接只能在 2MSL 結束後才能再被使用。在連接處於 2MSL 等待時,任何遲到的報文段將被丟棄。

  我們假設圖 3-12 中是客戶執行主動關閉並進入 TIME_WAIT ,這是正常的情況,因爲服務器通常執行被動關閉,不會進入 TIME_WAIT 狀態。這暗示如果我們終止一個客戶程序,並立即重新啓動這個客戶程序,則這個新客戶程序將不能重用相同的本地端口。這不會帶來什麼問題,因爲客戶使用本地 端口,而並不關心這個端口號是什麼。然而,對於服務器,情況就有所不同,因爲服務器使用周知端口。如果我們終止一個已經建立連接的服務器程序,並試圖立即 重新啓動這個服務器程序,服務器程序將不能把它的這個周知端口賦值給它的端點,因爲那個端口是處於 2MSL 連接的一部分。在重新啓動服務器程序前,它需要在 1~4 分鐘。這就是很多網絡服務器程序被殺死後不能夠馬上重新啓動的原因(錯誤提示爲“ Address already in use ”)。

 

 

本文摘自   http://wdqfirst.blog.163.com/blog/static/113347411201121511429120/

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