Tcp 斷開連接

TCP協議規定,對於已經建立的連接,網絡雙方要進行四次握手才能成功斷開連接,如果缺少了其中某個步驟,將會使連接處於假死狀態,連接本身佔用的資源不會被釋放。網絡服務器程序要同時管理大量連接,所以很有必要保證無用連接完全斷開,否則大量僵死的連接會浪費許多服務器資源。在衆多TCP狀態中,最值得注意的狀態有兩個:CLOSE_WAIT,TIME_WAIT。
1、LISTENING狀態
FTP服務啓動後首先處於偵聽(LISTENING)狀態。
2、ESTABLISHED狀態
ESTABLISHED的意思是建立連接。表示兩臺機器正在通信。
3、CLOSE_WAIT
對方主動關閉連接或者網絡異常導致連接中斷,這時我方的狀態會變成CLOSE_WAIT 此時我方要調用close()來使得連接正確關閉
4、TIME_WAIT

我方主動調用close()斷開連接,收到對方確認後狀態變爲TIME_WAIT。TCP協議規定TIME_WAIT狀態會一直持續2MSL(即兩倍的分段最大生存期),以此來確保舊的連接狀態不會對新連接產生影響。處於TIME_WAIT狀態的連接佔用的資源不會被內核釋放,所以作爲服務器,在可能的情況下,儘量不要主動斷開連接,以減少TIME_WAIT狀態造成的資源浪費。目前有一種避免TIME_WAIT資源浪費的方法,就是關閉socket的LINGER選項。但這種做法是TCP協議不推薦使用的,在某些情況下這個操作可能會帶來錯誤。

TCP連接關閉的幾種方式:

1、“正常”關閉:調用close()關閉socket、沒close但進程正常結束(當然這是不應該的做法)、進程core掉、在shell命令行中kill掉進程,都可抽象成“正常”關閉。因爲即使core掉,內核也會馬上幫應用程序回收(close)socket文件描述符。
“正常”關閉,默認情況下(非默認即設置Linger下面會介紹),關閉端即客戶端TCP層會發FIN包,對端即服務器TCP層收到後,回ACK,客戶端進入FIN_WAIT2狀態。此時,TCP終止連接的4個分組中服務器應該發的第3個分組FIN包,其TCP層是不會主動發的,只有服務器端socket“正常”關閉,纔會發出這個FIN包。至此,客戶端進入TIME_WAIT狀態。
2、“非”正常關閉:客戶端崩潰了,此時肯定發不出FIN包了(當然啦,內核都沒機會幫應用程序回收資源了)。這種情況,服務器端有如下兩種情況:
A、服務器send數據,因爲客戶端已經崩潰,服務器收不到ACK自然會不停的重傳。源自
Berkeley的重傳機制,重傳8次,相對第一次傳的15分鐘後仍沒收到ACK,則返回
ETIMEDOUT或EHOSTUNREAC錯誤。如果服務器不理會這個錯誤,再次調用send,則
立馬返回Broken Pipe錯誤。
注:15分鐘超時可以在 /proc/sys/net/ipv4/tcp_retries2 中修改
B、 服務器不發任何數據了,那只有靠應用層心跳檢測機制或Keepalive,來發覺TCP斷連了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章