CLOSE_WAIT
CLOSED
ESTABLISHED
FIN_WAIT_1
FIN_WAIT_2
LAST_ACK
LISTEN
SYN_RECEIVED
SYN_SEND
TIMED_WAIT
我覺得客戶端和服務(wù)端的狀態(tài)要分開來看坯临,不然盯著這個(gè)圖,一直沒法很清晰的分析它
服務(wù)端:
-本來沒有tcp毛事,CLOSED狀態(tài)
-開始監(jiān)聽后變成LISTEN狀態(tài)
客戶端:
-本來沒有tcp毛事桐筏,CLOSED狀態(tài)
-想建立連接給服務(wù)端發(fā)送SYN信號(hào)兄世,請(qǐng)求建立連接后變成SYN_SEND 代表我客戶端發(fā)送SYN了昂
服務(wù)端:
服務(wù)端收到這個(gè)SYN也不能置之不理鲸郊,把自己的狀態(tài)改成SYN_RECV代表我服務(wù)端收到SYN了昂
同時(shí)服務(wù)端需要回應(yīng)一個(gè)ACK SYN
客戶端:
客戶端收到服務(wù)端的ACK就知道這個(gè)服務(wù)端對(duì)頭~榨汤,很滿意然后把自己變成ESTABLISHED已經(jīng)建立連接狀態(tài)惶楼,并且回給服務(wù)端一個(gè)ACK
服務(wù)端:服務(wù)端看到客戶端回應(yīng)了自己的ACK ,也建立了連接滔以,將自己的狀態(tài)改成ESTABLISHED
四次揮手過程
客戶端和服務(wù)端本來互相收發(fā)消息捉腥,客戶端的狀態(tài)為ESATABLISHED 服務(wù)端的狀態(tài)也為ESATABLISHED
客戶端說我要關(guān)閉這個(gè)連接(主動(dòng)),給服務(wù)端發(fā)送了FIN你画,然后自己的狀態(tài)為FIN_WAIT1但狭,這個(gè)wait是在等待服務(wù)端的ACK
服務(wù)端收到這個(gè)FIN知道自己要被關(guān)閉了,返回一個(gè)ACK “老子知道了” 進(jìn)入CLOSE_WAIT撬即,這個(gè)wai是在等待自己將剩余消息全部發(fā)送給客戶端后主動(dòng)發(fā)起的一個(gè)close
客戶端收到ACK后狀態(tài)進(jìn)入FIN_WAIT2,這個(gè)wait在等待服務(wù)端的主動(dòng)關(guān)閉
好服務(wù)端就給你來個(gè)主動(dòng)關(guān)閉FIN呈队,然后自己的狀態(tài)為LAST_ACK等待最后一個(gè)ack的到來
客戶端收到這個(gè)FIN主動(dòng)關(guān)閉連接后給服務(wù)端發(fā)送一個(gè)ACK表示“收到你的關(guān)閉消息了”剥槐,將自己的狀態(tài)改成TIME_WAIT,這個(gè)wait顧名思義就是在等待時(shí)間,多少時(shí)間2個(gè)MSL的時(shí)間
2個(gè)MSL的時(shí)間后客戶端將自己的狀態(tài)改成CLOSED代表這個(gè)tcp連接關(guān)閉了
服務(wù)端收到這個(gè)ACK后也CLOSED關(guān)閉了連接
這里有幾個(gè)問題:
1.為什么一定要TIME_WAIT:
如果客戶端發(fā)送完最后一個(gè)ACK后就關(guān)閉了連接宪摧,服務(wù)端收到這個(gè)ACK也關(guān)閉了連接粒竖,本身是 沒有毛病
但是!如果網(wǎng)絡(luò)不好几于,服務(wù)端沒有收到這個(gè)ACK蕊苗,就會(huì)再次發(fā)送FIN,而這時(shí)客戶端已經(jīng)關(guān)閉了連接沿彭,怎么回應(yīng)嘛朽砰! 所以此時(shí)客戶端會(huì)恢復(fù)一個(gè)RST給客戶端,代表老子不懂你這個(gè)FIN,并且要求你關(guān)閉你的連接
并且如果沒有TIME_WAIT客戶端再次發(fā)起連接后可能受到這個(gè)FIN瞧柔,會(huì)影響到這次的連接
官方說法就是這時(shí)候其實(shí)連接已經(jīng)關(guān)閉漆弄,需要一個(gè)TIME—WAIT來將這個(gè)連接與下一個(gè)連接隔開,避免下一個(gè)連接再受到這個(gè)連接的重傳信號(hào)
2.客戶端為什么會(huì)堆積FIN_WAIT2:
如果你通過netstat看到客戶端堆積了大量的FIN_WAIT2造锅,原因有兩個(gè)
1.服務(wù)端無法發(fā)起主動(dòng)關(guān)閉FIN信號(hào)撼唾,導(dǎo)致客戶端收不到FIN將狀態(tài)切換到TIME_WAIT
2.服務(wù)單在CLOSE_WAIT狀態(tài)時(shí)死掉了,無法發(fā)送FIN