TCP连接(client、server)状态转换
?客戶端狀態的變化:
客戶端創建套接字之后會connect服務器,這時客戶端會發送一個SYN到服務器,狀態轉換到SYN_SENT并等待服務器的回復,收到服務端的回復SYN+ACK(同一個報文)之后???客戶端會回復ACK此時狀態轉換到ESTABLISHED,正常數據交互完成之后客戶端會close套接字此時發送一個FIN報文,狀態轉換到FIN_WAIT_1,同時等待服務端的回復,此時有三種情況:
(1)收到服務端的ACK但此時服務端沒有關閉套接字。狀態轉換到了FIN_WAIT_2,然后再等待服務端關閉套接字發出的FIN,如果收到則回復ACK,狀態轉換到TIME_WAIT狀態,等待2MSL超時之后自動轉換為CLOSED狀態。
?(2)服務端同時也在關閉套接字,此時客戶端會收到SYN并發出ACK,狀態轉換到CLOSING,之后等待服務端回復ACK,若收到ACK則轉到TIME_WAIT狀態。
(3)服務器在收到客戶端FIN之后立馬關閉套接字,此時客戶端會收到一個ACK和FIN并發出ACK,狀態?轉換到TIME_WAIT狀態。
服務器狀態的變化:
服務端?創建套接字之后調用listen函數將套接字有一個未連接的主動套接字轉換為被動套接字,指示內核應接受指向該套接字的連接請求,套接字狀態由CLOSE轉換為LISTEN,等待客戶端連接。所以服務端是被動接收連接的,服務端會先收到SYN,收到之后會立馬發送一個SYN+ACK(同一個報文),此時狀態轉換到SYN_RCVD并等待客戶端回復ACK,此時套接字處于未完成連接隊列中,如果收到ACK狀態會轉換到ESTABLISHED,套接字處于已完成連接隊列中,注意的是未完成連接隊列和已完成連接隊列之和不能超過listen設置的最大連接個數。這時服務端和客戶端可以進行數據交互,客戶端接收完數據之后主動close套接字,此時服務端會收到FIN并回復ACK,狀態轉換到LOSE_WAIT,當服務端的應用層也close套接字時服務端會發生一個FIN狀態轉換到LAST_ACK然后會收到客戶端回復的ACK,狀態轉換到CLOSED。
為什么釋放連接需要TIME_WAIT?
回憶一下我們最終的那個FIN與ACK,被動關閉方發送FIN,并等待主動關閉方返回的ACK。我們假設最終的ACK丟失,被動關閉方將需要重新發送它的最終那個FIN,主動關閉方必須維護狀態信息(TIME_WAIT),以允許它重發最終的那個ACK。如果沒有了這個狀態,當他第二次收到FIN時,會響應一個RST(也是一種類型的TCP分節),會被服務器解釋成一個錯誤。
目的:為了TCP打算執行必要的工作以徹底終止某個連接兩個方向上的數據流(即全雙工關閉),那么他必須要正確處理連接終止四個分節中任何一個分節丟失的情況
處于TIME_WAIT這個狀態時,此套接字上的綁定了資源,將在2MSL(最大報文生存時間)內不可再使用。選擇2MSL這個時間是為了避免出現上一次連接中被動關閉端重復發送的數據包。
我們假設ip1:port1和ip2:port2 之間有一個TCP連接。我們關閉了這個鏈接,過一段時間后在相同IP和端口之間建立了另一個連接。TCP必須防止來自之前那個連接的老的重復分組在新連接上出現。為了做到這一點,TCP將不復用處于TIME_WAIT狀態的連接。2MSL的時間足以讓某個方向上的分組存活MSL秒后被丟棄,另一個方向上的應答也最多存活MSL秒后被丟棄。
狀態轉換圖:
?
轉載于:https://www.cnblogs.com/single-dont/p/11386241.html
總結
以上是生活随笔為你收集整理的TCP连接(client、server)状态转换的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Vue.js not detected
- 下一篇: 新版本,新起点。