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斷連了。
TCP連線和斷開連線
4.4 tcp資料報結構 帶陰影的幾個字段需要重點說明一下 1 序號 seq sequence number 序號佔32位,用來標識從計算機a傳送到計算機b的資料報的序號,計算機傳送資料時對此進行標記。2 確認號 ack acknowledge number 確認號佔32位,客戶端和伺服器端都可以傳...
TCP連線與斷開
a機器與b機器三次握手檢驗雙方報文收發正常 第一次握手 a請求連線 syn 1,seq x b正常接收 ab a能發報 b能收報 第二次握手 syn 1,ack 1,seq y,ack x 1 a a能發報 收報,b能發報 收報 b a能發報 b能收報 第三次握手 ack 1,seq x 1,ack...
tcp的連線斷開
tcp的斷開連線是需要主機完成四次揮手的過程的,並不是斷網了就表示斷開連線了。假如雙方已經建立起了連線,突然一方斷網 比如突然停電,或者網線突然被拔了 對於另一方來講他並不會知道這個情況,他依然認為連線是沒有斷開的。四次揮手的過程是由系統完成的。如果要斷開連線,要麼是程序發起系統呼叫。或者,這個程序...