談一談TCP的4次揮手

 戳藍字「TopCoder」關注我們哦!

TCP是全雙工傳輸協議,也就是說雙方都可進行讀寫操作,當一方不需要寫數據時,會通過發送FIN報文告知對方,我要關閉連接了,對方接受到並返回ACK報文,這就表示一方的連接已經關閉,此時另一方的連接還是OK的,也就是說另一方還是可以繼續寫數據的,等到另一方也發完數據之後就可以發送FIN報文。

注意,接收到FIN報文時系統只能返回一個ACK,它無法發出FIN報文,因此FIN報文的發出是由業務層來觸發的。

4次揮手流程

TCP建立連接到4次揮手流程如下:

注意,4次揮手流程有一個TIME_WAIT階段(TIME_WAIT的作用是保證關閉連接後這個連接在網絡中的所有數據包都過期,否則的話可能存在這樣的問題,連接關閉了但是網絡中還殘留舊連接的報文,這樣如果以同樣的TCP 4元組新建的連接可能會接收到該舊報文,會以爲是新連接的報文而導致問題),更詳細的4次揮手流程如下:

4次揮手中的問題分析

從4次揮手的流程來看,可能存在問題的地方有,主動斷開連接端的FIN_WAIT_2和TIME_WAIT階段,被動斷開連接端的CLOSE_WAIT階段:

CLOSE_WAIT階段

正常情況下CLOSE_WAIT存在的時間很短,因爲稍後被動關閉端會發出FIN報文,然後進到 LAST_ACK 狀態。如果系統中存在較多的CLOSE_WAIT 狀態的連接,說明是本端服務沒有處理好,比如:

  • 本身程序問題:應用層忘記進行close,或者close不及時,再或者應用沒有及時對端發送來的FIN報文響應close動作;

  • 新建連接太多問題:比如存在(3次握手中的)已連接隊列中的連接未被應用及時accept導致客戶端已經close了,此時連接就處於CLOSE_WAIT階段了。

出現了CLOSE_WAIT 狀態連接過多,只要確定了是什麼原因,就可以對症解決了,這裏不再贅述。

FIN_WAIT_2階段

正常情況下FIN_WAIT_2階段的存在時間也很短,因爲對端會很快發出FIN報文,如果發現處於FIN_WAIT_2狀態的連接過多,說明是對端沒有及時發出FIN報文,這個是對端的原因,本端無法控制,不過本端可以設置FIN_WAIT_2的超時時間,對於配置項爲 net.ipv4.tcp_fin_timeout ,來避免該問題。

TIME_WAIT階段

當 TCP 連接主動關閉時,都會經過 TIME_WAIT 狀態,TIME_WAIT存在的意義是保證關閉連接後這個連接在網絡中的所有數據包都過期,否則的話可能存在這樣的問題,連接關閉了但是網絡中還殘留舊連接的報文,這樣如果以同樣的TCP 4元組新建的連接可能會接收到該舊報文,會以爲是新連接的報文而導致問題,因此TIME_WAIT 的存在是爲了保證網絡中迷失的數據包正常過期。

說到過期時間,就不得不提 最大分段壽命(MSL, Maximum Segment Lifetime),它表示一個 TCP 分段可以存在於互聯網系統中的最大時間,由 TCP 的實現,超出這個壽命的分片都會被丟棄。

MSL 的時長被 RFC 定義爲 2分鐘,但在不同的 unix 實現上,這個值不併確定,我們常用的 centOS 上,它被定義爲 30s,我們可以通過 /proc/sys/net/ipv4/tcp_fin_timeout 這個文件查看和修改這個值。

TIME_WAIT階段存在的問題是 TIME_WAIT 狀態連接過多,會佔用過多的句柄資源,嚴重時系統無法發起新的連接。可以通過配置來設定超時時間、TIME_WAIT連接重用等機制:

net.ipv4.tcp_tw_reuse = 1 表示開啓重用。允許將TIME-WAIT sockets重新用於新的TCP連接,默認爲0,表示關閉;
net.ipv4.tcp_tw_recycle = 1 表示開啓TCP連接中TIME-WAIT sockets的快速回收,默認爲0,表示關閉。
net.ipv4.tcp_fin_timeout 修改系默認的 TIMEOUT 時間

 推薦閱讀 


歡迎小夥伴關注【TopCoder】閱讀更多精彩好文。

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