1. 程式人生 > 實用技巧 >TCP的有限狀態機

TCP的有限狀態機

TCP是一個可靠的連線,每一次建立通訊都必須通過三次握手四次揮手來完成一次通訊任務,現在就來介紹tcp的建立連線與釋放連線

1 TCP的建立連線

為什麼需要三次握手來建立連線?

為什麼A還要傳送一次確認呢?這主要是為了防止已失效的連線請求報文段突然又傳送到了B,因而產生錯誤。所謂已失效的連線請求報文段是這樣產生的。A傳送連線請求,但因連線請求報文丟失而未收到確認,於是A重發一次連線請求,成功後建立了連線。資料傳輸完畢後就釋放了連線。現在假定A發出的第一個請求報文段並未丟失,而是在某個網路節點長時間滯留了,以致延誤到連線釋放以後的某個時間才到達B。本來這是一個早已失效的報文段。但B收到此失效的連線請求報文段後,就誤以為A又發了一次新的連線請求,於是向A發出確認報文段,同意建立連線。假如不採用三次握手,那麼只要B發出確認,新的連線就建立了。由於A並未發出建立連線的請求,因此不會理睬B的確認,也不會向B傳送資料。但B卻以為新的運輸連線已經建立了,並一直等待A發來資料,因此白白浪費了許多資源。採用TCP三次握手的方法可以防止上述現象發生。例如在剛才的情況下,由於A不會向B的確認發出確認,連線就不會建立。

2.資料傳輸

3.釋放連線

為什麼需要四次揮手來釋放連線?

  1. 為了保證A傳送的最後一個ACK報文段能夠到達B。即最後這個確認報文段很有可能丟失,那麼B會超時重傳,然後A再一次確認,同時啟動2MSL計時器,如此下去。如果沒有等待時間,傳送完確認報文段就立即釋放連線的話,B就無法重傳了(連線已被釋放,任何資料都不能出傳了),因而也就收不到確認,就無法按照步驟進入CLOSE狀態,即必須收到確認才能close。
  2. 防止“已失效的連線請求報文段”出現在連線中。經過2MSL,那些在這個連線持續的時間內,產生的所有報文段就可以都從網路中消失。即在這個連線釋放的過程中會有一些無效的報文段滯留在樓閣結點,但是呢,經過2MSL這些無效報文段就肯定可以傳送到目的地,不會滯留在網路中。這樣的話,在下一個連線中就不會出現上一個連線遺留下來的請求報文段了。

4.TCP有限狀態機

  1. CLOSED 狀態時初始狀態。

  2. LISTEN:被動開啟,伺服器端的 狀態變為LISTEN(監聽)。被動開啟的概念:連線的一端的應用程式通知作業系統,希望建立一個傳入的連線。這時候作業系統為連線的這一端建立一個連 接。與之對應的是主動連線:應用程式通過主動開啟請求來告訴作業系統建立一個連線。

  3. SYNRECVD:伺服器端收到SYN後,狀態為SYN;傳送SYN ACK;

  4. SYN_SENTY:應用程式傳送SYN後,狀態為SYN_SENT;

  5. ESTABLISHED:SYNRECVD收到ACK後,狀態為ESTABLISHED; SYN_SENT在收到SYN ACK,傳送ACK,狀態為ESTABLISHED;

  6. CLOSE_WAIT:伺服器端在收到FIN後,傳送ACK,狀態為CLOSE_WAIT;如果此時伺服器端還有資料需要傳送,那麼就傳送,直到資料傳送完畢;此時,伺服器端傳送FIN,狀態變為LAST_ACK;

  7. FIN_WAIT_1:應用程式端傳送FIN,準備斷開TCP連線;狀態從ESTABLISHED——>FIN_WAIT_1;

  8. FIN_WAIT_2:應用程式端只收到伺服器端得ACK訊號,並沒有收到FIN訊號;說明伺服器端還有資料傳輸,那麼此時為半連線;

  9. TIME_WAIT:有兩種方式進入 該狀態:1、FIN_WAIT_1進入:此時應用程式埠收到FIN+ACK(而不是像FIN_WAIT_2那樣只收到ACK,說明資料已經發送完畢)並 向伺服器埠傳送ACK;2、FIN_WAIT_2進入:此時應用程式埠收到了FIN,然後向伺服器端傳送ACK;TIME_WAIT是為了實現TCP 全雙工連線的可靠性關閉,用來重發可能丟失的ACK報文;需要持續2個MSL(最大報文生存時間):假設應用程式埠在進入TIME_WAIT後,2個 MSL時間內並沒有收到FIN,說明應用程式最後發出的ACK已經收到了;否則,會在2個MSL內在此收到ACK報文;