1. 三次握手:
服務器一定處於Listen狀態,否則客戶端發過來的連接會被拒絕。注:服務器和客戶端的角色是相對的。
客戶端發送第一次握手(客戶端發送連接請求(SYNC包)到服務器)之后由Closed狀態轉為Sync-Send狀態;
服務器收到第一次握手的客戶端SYNC包,然后發送第二次握手(服務器發送SYNC+ACK(客戶端SYNC包的確認)包給客戶端)之后服務器由Listen狀態轉為Sync-Recv狀態;
客戶端收到第二次握手的服務器SYNC+ACK包,然后發送第三次握手(客戶端對“服務器的SYNC+ACK包“的ACK包給給服務器)之后客戶端就轉為ESTABLISHED狀態;
服務器收到第三次握手的客戶端ACK包之后也進入了ESTABLISHED。
2. 四次揮手:
服務器與客戶端都處於ESTABLISHED狀態,且有一方主動發起了關閉,另外一方會被動關閉。被動關閉的一方需要處理socket的資源回收等,被動關閉的一方需要及時關閉,所以說被動關閉的一方出現大量CLOSE_WAIT狀態通常都是因為程序代碼問題。
主動關閉的一方(可能是服務器也可能是客戶端)的狀態遷移:FIN-WAIT1->FIN-WAIT2->TIME_WAIT-CLOSED
被動關閉的一方的狀態遷移:CLOSE_WAIT->LAST_ACK->CLOSED
同時關閉:雙方狀態一致: FIN_WAIT1->CLOSING->TIME_WAIT
假設客戶端主動關閉連接,以下說明客戶端和服務器如何遷移:
客戶端發送第一次揮手(客戶端第一個FIN包給服務器)之后由ESTABLISHED狀態轉為FIN_WAIT1狀態;
服務器收到客戶端的第一次揮手(客戶端第一個FIN包給服務器)之后,發送第二次揮手(對客戶端FIN的ACK確認包)給服務器,服務器進入CLOSE_WAIT狀態,等待服務器自身的socket關閉等處理(等待IO,業務處理,資源回收等等);
客戶端收到服務器的第二次揮手(對客戶端FIN的ACK確認包),進入FIN_WAIT2狀態,等待服務器關閉(服務器調用close函數發送服務器的FIN包);
服務器發送第三次揮手(在處理完自己的事情,調用close函數之后,發送服務器的FIN包),進入LAST_ACK狀態;
客戶端收到第三次揮手(服務器的FIN包),發送第四次揮手(客戶端第二個FIN包+ACK(對服務器FIN包的確認)),客戶端進入TIME_WAIT狀態;
服務器收到第四次揮手(客戶端第二個FIN包+ACK(對服務器FIN包的確認)),進入CLOSED狀態;
客戶端等待2MSL時間,進入CLOSED狀態
注:FIN_WAIT2狀態等待時間是有限的,系統可配:tcp_fin_timeout 這個參數可以控制改狀態存活的時間
FIN_WAIT1和CLOSE_WAIT是比較危險的狀態,一般服務器網絡鼓掌首先要查看這倆個狀態是否正常:CLOSE_WAIT在上面說過,如果服務器代碼有問題(忘記close等),服務器會一直有需要的CLOSE_WAIT狀態的socket,造成服務器不可連接;FIN_WAIT1會在發出來FIN而沒有手到ACK會重新發送FIN,重發次數由系統參數配置:tcp_orphan_retries;如果系統負載過重,減少tcp_orphan_retries值可能有作用。
一般來說FIN_WAIT1幾乎不可見,因為服務器之間的ACK速度非常快;
FIN_WAIT1 的DDos攻擊舉例說明:http://huoding.com/2014/11/06/383
參考:http://coolshell.cn/articles/1484.html
TCP共有11個網路狀態,其中涉及到關閉的狀態有5個。
在我們編寫網絡相關程序的時候,這5個狀態經常出現。因為這5個狀態相互關聯,相互糾纏,而且狀態變化觸發都是由應用觸發,但是又涉及操作系統和網絡,所以正確的理解TCP 在關閉時網絡狀態變化情況,為我們診斷網絡中各種問題,快速定位故障有着非常重要的作用和意義。
下是是根據W.Richard Stevens的《TCP/IP詳解》一書的TCP狀態轉換圖。





