天天看點

TCP學習-TCP連接配接釋放與TCP狀态圖

參考:http://blog.sina.com.cn/s/blog_417b97470100ohv1.html

http://www.cnblogs.com/rootq/articles/1377355.html

一、TCP的簡要介紹

      TCP(Transmission Control Protocol) 傳輸控制協定

      TCP 是一個面向連接配接的協定,無論哪一方向另一方發送資料之前,都必須先在雙方之間建立一條連接配接。

二、TCP的連接配接      通過三次握手後,建立一個連接配接

tcp有6種位碼(即标志位)

SYN:synchronous建立聯機

ACK:acknowledgement 确認标志位,與下面的AcknowledgeNumber有差別的

PSH:push傳送

FIN:finish結束

RST:reset重置

URG:urgent緊急

Seq:SequenceNumber 順序号碼

AcknowledgeNumber:确認号碼

第一次握手:主機A發送位碼為SYN=1,随機産生Seq=1234567的資料包到伺服器,主機B由SYN=1知道,A要求建立聯機;

第二次握手:主機B收到請求後要确認聯機資訊,向A發送AcknowledgeNumber=(主機A的Seq+1),SYN=1,ACK=1,随機産生Seq=7654321的包

第三次握手:主機A收到後檢查AcknowledgeNumber是否等于第一次握手發送的Seq+1,以及位碼ACK是否為1,若正确,主機A會再發送AcknowledgeNumber=(主機B的Seq+1),ack=1,主機B收到後确認seq值與ack=1則連接配接建立成功。

如圖所示:

TCP學習-TCP連接配接釋放與TCP狀态圖

完成三次握手,主機A與主機B開始傳送資料。

     發送第一個 SYN 的一端将執行主動打開( active open ),接收這個 SYN 并發回下一個 SYN 的另一端執行被動打開( passive open )。另外, TCP 的握手協定被精心設計為可以處理同時打開( simultaneous open ),對于同時打開它僅建立一條連接配接而不是兩條連接配接。是以,連接配接可以由任一方或雙方發起,一旦連接配接建立,資料就可以雙向對等地流動,而沒有所謂的主從關系。

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

   三次握手協定可以完成兩個重要功能:它確定連接配接雙方做好傳輸準備,并使雙方統一了初始順序号。初始順序号是在握手期間傳輸順序号并獲得确認:當一端為建立連接配接而發送它的 SYN 時,它為連接配接選擇一個初始順序号;每個封包段都包括了順序号字段和确認号字段,這使得兩台機器僅僅使用三個握手封包就能協商好各自的資料流的順序号。 

三、TCP的關閉

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

TCP學習-TCP連接配接釋放與TCP狀态圖

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

 連接配接的關閉有三種情況:

•  本方啟動關閉

   收到本方應用程序的關閉指令後, 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 )來表示,下圖描述了 TCP 的有限狀态機,圖中的圓角矩形表示狀态,箭頭表示狀态之間的轉換。圖中用粗線表示用戶端主動和被動的伺服器端建立連接配接的正常過程:用戶端的狀态變遷用粗實線,伺服器端的狀态變遷用粗虛線。細線用于不常見的序列,如複位、同時打開、同時關閉等。圖中的每條狀态變換線上均标有“事件/動作”:事件是指使用者執行了系統調用( CONNECT 、 LISTEN 、 SEND 或 CLOSE )、收到一個封包段( SYN 、 FIN 、 ACK 或 RST )、或者是出現了超過兩倍最大的分組生命期的情況;動作是指發送一個封包段( SYN 、 FIN 或 ACK )或什麼也沒有(用“-”表示)。

TCP學習-TCP連接配接釋放與TCP狀态圖

 TCP 狀态表描述

CLOSED :關閉狀态,沒有連接配接活動或正在進行

LISTEN :監聽狀态,伺服器正在等待連接配接進入

SYN RCVD: 收到一個連接配接請求,尚未确認

SYN SENT :已經發出連接配接請求,等待确認

ESTABLISHED: 連接配接建立,正常資料傳輸狀态

FIN WAIT 1 :(主動關閉)已經發送關閉請求,等待确認

FIN WAIT 2 :(主動關閉)收到對方關閉确認,等待對方關閉請求

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

CLOSING :雙方同時嘗試關閉,等待對方确認

CLOSE WAIT: (被動關閉)收到對方關閉請求,已經确認

LAST ACK :(被動關閉)等待最後一個關閉确認,并等待所有分組死掉

 1. 正常狀态轉換

a、伺服器端首先執行 LISTEN 原語進入被動打開狀态( LISTEN ),等待用戶端連接配接;

b、當用戶端的一個應用程式發出 CONNECT 指令後,本地的 TCP 實體為其建立一個連接配接記錄并标記為 SYN SENT 狀态,然後給伺服器發送一個 SYN 封包段;

c、伺服器收到一個 SYN 封包段,其 TCP 實體給用戶端發送确認 ACK 封包段同時發送一個 SYN 信号,進入 SYN RCVD 狀态;

d、用戶端收到 SYN + ACK 封包段,其 TCP 實體給伺服器端發送出三次握手的最後一個 ACK 封包段,并轉換為 ESTABLISHED 狀态;

e、伺服器端收到确認的 ACK 封包段,完成了三次握手,于是也進入 ESTABLISHED 狀态。

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

a、用戶端執行 CLOSE 原語,本地的 TCP 實體發送一個 FIN 封包段并等待響應的确認(進入狀态 FIN WAIT 1 );

b、伺服器收到一個 FIN 封包段,它确認用戶端的請求發回一個 ACK 封包段,進入 CLOSE WAIT 狀态;

c、用戶端收到确認 ACK 封包段,就轉移到 FIN WAIT 2 狀态,此時連接配接在一個方向上就斷開了;

d、伺服器端應用得到通告後,也執行 CLOSE 原語關閉另一個方向的連接配接,其本地 TCP 實體向用戶端發送一個 FIN 封包段,并進入 LAST ACK 狀态,等待最後一個 ACK 确認封包段;

e、用戶端收到 FIN 封包段并确認,進入 TIMED WAIT 狀态,此時雙方連接配接均已經斷開,但 TCP 要等待一個 2 倍封包段最大生存時間 MSL ( Maximum Segment Lifetime ),確定該連接配接的所有分組全部消失,以防止出現确認丢失的情況。當定時器逾時後, TCP 删除該連接配接記錄,傳回到初始狀态( CLOSED )。

f、伺服器收到最後一個确認 ACK 封包段,其 TCP 實體便釋放該連接配接,并删除連接配接記錄,傳回到初始狀态( CLOSED )。

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 顯示了這些狀态變遷過程。

圖 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 總結了這些狀态的變化,從圖中可以看出同時關閉與正常關閉使用的封包段交換數目相同。

圖 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 ”)。

小結

   和 IP 一樣, TCP 也是 TCP/IP 協定簇中最為重要的協定。本章詳細地介紹了 TCP 的工作原理、資料報格式,特别是 TCP 連接配接建立與關閉的狀态轉換。由于 TCP 是離應用層最近的底層協定,是以 TCP 的很多狀态在上層應用中是可見的,在後面的章節中,很多地方都涉及到 TCP 的各種狀态。是以,掌握本章介紹的原理和概念,對于學好後面的章節極為有利,特别是掌握了 TCP 的狀态轉換規律,對于網絡的配置與診斷、以及網絡應用的調試大有裨益。

參考:http://blog.sina.com.cn/s/blog_417b97470100ohv1.html

http://www.cnblogs.com/rootq/articles/1377355.html

繼續閱讀