tcp有限狀態機分析

 

tcp有限狀態機

 

這幅圖是TCP的狀態機,看了2個小時,分析總結如下:

(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報文;

 

 2011.9.14補充:

關閉的狀態轉換比較複雜:現在設通信雙方是A,B,A是主動發起關閉方

(1)      主動發起關閉方:

A首先主動發起FIN報文,準備關閉TCP連接,然後進入FIN_WAIT1狀態;然後,如果A收到了ACK報文,就進入FIN_WAIT2狀態;而如果A收到的是ACK + FIN,A進入TIME_WAIT狀態。

進入FIN_WAIT2狀態,說明B還有數據發給A。過了不久之後,B發送FIN給A,然後,A發送ACK,並進入TIME_WAIT狀態。當2個MSL內,沒有收到FIN信號,那麼TIME_WAIT就自動轉化爲CLOESD。(爲什麼TIME_WAIT狀態要進過2個MSL(Maximum Segment Lifetime.)才能進入CLOSED狀態?假設網路是不可靠的,最後A發出的ACK信號丟失,那麼B就沒有收到ACK,此時B還需要重新發一個FIN給A,這個過程最多需要2MSL,所以如果過了2MSL,沒有再次收到B的FIN,那麼,說明之間A發出的ACK被B收到了,所以可以可靠地關閉連接。)

(2)      被動接收方

B在收到A的FIN報文後,知道A準備關閉 TCP連接了(注意只是A單方面關閉,也就是說,A還可以收數據,但是不準備發數據了)。B將發送ACK給A,然後B進入CLOSED_WAIT狀態。如 果此時B也有數據發送給A,那麼就一直髮送好了,反正A不會發數據了。此時A處於FIN_WAIT2狀態。當B的數據發送完畢之後,那麼B發送FIN給 A,B進入LAST_ACK狀態。當收到A發過來的ACK信號後,A進入CLOSED狀態。

問題:

1、 爲什麼建立連接協議是三次握手,而關閉連接卻是四次握手呢
這是因爲服務端的LISTEN狀態下的SOCKET當收到SYN報文的建連請求後,它可以把ACK和SYN(ACK起應答作用,而SYN起同步作用)放在 一個報文裏來發送。但關閉連接時,當收到對方的FIN報文通知時,它僅僅表示對方沒有數據發送給你了;但未必你所有的數據都全部發送給對方了,所以你可以 未必會馬上會關閉SOCKET,也即你可能還需要發送一些數據給對方之後,再發送FIN報文給對方來表示你同意現在可以關閉連接了,所以它這裏的ACK報 文和FIN報文多數情況下都是分開發送的。

TCP的關閉連接的時候,狀態很多,以剛纔的例子分類:一個是主動發起方涉及的狀態,一個被動發起方涉及的狀態:

 

主動發起方:

FIN_WAIT1(發出FIN信號)

FIN_WAIT2(收到ACK信號)

TIME_WAIT(收到FIN信號)

CLOSED(2個MSL後,沒有再次收到FIN,進入)

 

被動接收方:

CLOSED_WAIT(收到FIN信號)

LAST_ACK(發出FIN信號)

CLOSED(收到ACK信號,如果沒有,再次發出FIN信號)

2.爲什麼能三次握手、四次揮手可靠地建立關閉連接?

注意可靠。

答:在建立連接的時候,首先需要發起方發出請求(即發出帶有SYN的報文),接收方收到後必須給發起方一個迴應(ACK+SYN)

,關鍵是這裏還沒有完畢。因爲網絡是不可靠地,(a)如果發起方沒有收到應答方的ACK+SYN報文,顯然,說明報文丟失,必須重發請求;(b)如果發起方收到ACK+SYN後,不再向接收方發出ACK信號(更正於2011.9.17)(也 就是隻有兩次握手,此時開始傳遞報文),那麼從發起方的角度來看,它認爲自己發出的ACK+SYN報文丟失了,接收方沒有收到,所以它會再次重發。(c) 當發起方發出ACK信號後,如果沒有收到接收方再次發來的ACK+SYN報文,那麼說明接收方收到了自己發出的ACK報文,所以可以建立連接了。

舉個例子,如何保障可靠通信:

現在A和B兩支軍隊準備在10:00同時發起進攻,如何才能保證這兩支軍隊同時呢?

現在A發出電報,“要求在10:00同時發起進攻”;

B收到後,顯然必須向A回覆“收到,可以”。

A在收到“收到,可以”的消息後,直到B已 經收到了自己發出的消息。注意,這裏還沒有完,如果你站在B的角度去思考:“我發出了‘收到,可以’的消息,必須要求A給我一個迴應。如果我沒有收到回 應,那麼就說明我的這個消息沒有送到A那裏去”,那麼,我得再傳一次“收到,可以”的消息跟A。所以,A必須再次發出“你的消息已經收到”的消息發送給 B。此時,如果A沒有再次收到B發來的“收到,可以”的消息,就可以認爲自己的“你的消息已經收到”送給了B。而實際上,如果B收到A發來的“你的消息”我已經收到,說明,自己此前發出的消息已經被A收到。

這樣,就可以保證A,B可靠地收到消息,保證他們在10:00準時發起進攻。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章