過程以下:服務器
1)主機A發送位碼爲FIN=1,用來關閉客戶A到服務器B的數據傳送。此時A的狀態爲FIN_WAIT_1
2)服務器B收到這個FIN,它發回一個ACK,確認序號爲收到的序號加1。此時A爲FIN_WAIT_2,B爲CLOSE_WAIT
3)服務器B關閉與客戶端A的鏈接,發送一個FIN給客戶端A。此時A爲TIME_WAIT,B爲LAST_ACK
4)客戶端A發回ACK報文確認,並將確認序號設置爲收到序號加1。此時A、B都關閉了,狀態變爲CLOSED。
當(2)、(3)步中的ACK和FIN在一個包中發送時,A的狀態會直接從FIN_WAIT_1變爲TIME_WAIT 併發
爲何創建鏈接須要三次握手,而斷開鏈接須要四次握手?ide
由於每一個方向都須要一個FIN和ACK,當一端發送了FIN包以後,處於半關閉狀態,此時仍然能夠接收數據包。 spa
在創建鏈接時,服務器能夠把SYN和ACK放在一個包中發送。 blog
可是在斷開鏈接時,若是一端收到FIN包,但此時仍有數據未發送完,此時就須要先向對端回覆FIN包的ACK。等到將剩下的數據it
都發送完以後,再向對端發送FIN,斷開這個方向的鏈接。 class
所以不少時候FIN和ACK須要在兩個數據包中發送,所以須要四次握手 im
中各類狀態的含義d3
FIN_WAIT_1: 這個狀態要好好解釋一下,其實 FIN_WAIT_1 和 FIN_WAIT_2 狀態的真正含義都是表示等待對方的 FIN 報文。而這兩數據
種狀態的區別是:FIN_WAIT_1 狀態其實是當 SOCKET 在 ESTABLISHED 狀態時,它想主動關閉鏈接,向對方發送了 FIN 報文,此
時該 SOCKET 即進入到 FIN_WAIT_1 狀態。而當對方迴應 ACK 報文後,則進入到 FIN_WAIT_2 狀態,固然在實際的正常狀況下,無
論對方何種狀況下,都應該馬 上回應 ACK 報文,因此 FIN_WAIT_1 狀態通常是比較難見到的,而 FIN_WAIT_2 狀態還有時經常可
以用 netstat 看到。
FIN_WAIT_2:上面已經詳細解釋了這種狀態,實際上 FIN_WAIT_2 狀態下的 SOCKET,表示半鏈接,也即有一方要求 close 鏈接,但
另外還告訴對方,我暫時還有點數據須要傳送給你,稍後再關閉鏈接。
TIME_WAIT: 表示收到了對方的 FIN 報文,併發送出了 ACK 報文,就等 2MSL 後便可回到 CLOSED 可用狀態了。若是 FIN_WAIT_1
狀態下,收到了對方同時帶 FIN 標誌和ACK 標誌的報文時,能夠直接進入到 TIME_WAIT 狀態,而無須通過 FIN_WAIT_2 狀態。
CLOSING(圖中沒有標誌這種狀態): 這種狀態比較特殊,實際狀況中應該是不多見,屬於一種比較罕見的例外狀態。正常狀況下,當
你發送 FIN 報文後,按理來講是應該先收到(或同時收到)對方的 ACK 報文,再收到對方的 FIN 報文。可是 CLOSING 狀態表示
你發送 FIN 報文後,並無收到對方的 ACK 報文,反而卻也收到了對方的 FIN 報文。什麼狀況下會出現此種狀況呢?其實細想一
下,也不可貴出結論:那就是若是雙方几乎在同時close一個 SOCKET 的話,那麼就出現了雙方同時發送 FIN 報文的狀況,也即會出
現 CLOSING 狀態,表示雙方都正在關閉 SOCKET 鏈接。
CLOSE_WAIT: 這種狀態的含義實際上是表示在等待關閉。怎麼理解呢?當對方 close 一個 SOCKET 後發送 FIN 報文給本身,你係統毫
無疑問地會迴應一個 ACK 報文給對方,此時則進入到 CLOSE_WAIT 狀態。接下來呢,實際上你真正須要考慮的事情是察看你是否還
有數據發送給對方,若是沒有的話,那麼你也就能夠 close 這個 SOCKET,發送 FIN 報文給對方,也即關閉鏈接。因此你在 CLOSE_WAIT
狀態下,須要完成的事情是等待你去關閉鏈接。
LAST_ACK: 這個狀態仍是比較容易好理解的,它是被動關閉一方在發送 FIN 報文後,最後等待對方的 ACK 報文。當收到 ACK 報文後
,也便可以進入到 CLOSED 可用狀態了。