
我知道有很多關於此的 SE 問題,我相信在討論這一點之前我已經閱讀了盡可能多的問題。
我所說的「伺服器端TIME_WAIT
」是指在伺服器端啟動其 close() 的伺服器端套接字對的狀態。
我常看到這些聽起來與我矛盾的說法:
- 伺服器端
TIME_WAIT
是無害的 - 您應該設計您的網頁應用程序,讓客戶端啟動 close(),因此讓客戶端承擔
TIME_WAIT
我發現這種矛盾的原因是因為TIME_WAIT
在客戶端可能會出現問題 - 客戶端可能會耗盡可用端口,因此本質上,上述內容建議將負擔轉移到TIME_WAIT
可能出現問題的客戶端,從伺服器端這不是問題。
TIME_WAIT
當然,客戶端只是有限數量的用例的問題。大多數客戶端-伺服器解決方案都涉及一台伺服器和許多客戶端,客戶端通常不會處理足夠多的連接,因此這會成為一個問題,即使它們這樣做,也有許多「理智」的建議(與0 超時相反,或乾擾 tcp_tw sysctls)透過避免太快建立太多連線來SO_LINGER
對抗客戶端。TIME_WAIT
但這並不總是可行,例如對於以下應用程式類別:
- 監控系統
- 負載產生器
- 代理商
另一方面,我什至不明白伺服器端TIME_WAIT
有什麼幫助。原因TIME_WAIT
就在那裡,因為它可以防止將過時的TCP
片段注入到它們不再屬於的流中。對於客戶端,TIME_WAIT
它是透過簡單地使其不可能創建與ip:port
此過時連接可能具有的相同對的連接來完成的(已使用的對被鎖定TIME_WAIT
)。但是對於伺服器端來說,這是無法阻止的,因為本地地址將具有接受端口,並且總是相同的,並且伺服器不能(AFAIK,我只有經驗證明)僅僅因為拒絕連接傳入的對等點將創建套接字表中已存在的相同位址對。
我確實編寫了一個程序,顯示伺服器端的 TIME-WAIT 被忽略。此外,因為測試是在 127.0.0.1 上完成的,所以核心必須有一個特殊的位,甚至可以告訴它是伺服器端還是客戶端(否則元組將是相同的)。
來源:http://pastebin.com/5PWjkjEf,在 Fedora 22 上測試,預設網路配置。
$ gcc -o rtest rtest.c -lpthread
$ ./rtest 44400 s # will do server-side close
Will initiate server close
... iterates ~20 times successfully
^C
$ ss -a|grep 44400
tcp TIME-WAIT 0 0 127.0.0.1:44400 127.0.0.1:44401
$ ./rtest 44500 c # will do client-side close
Will initiate client close
... runs once and then
connecting...
connect: Cannot assign requested address
因此,對於伺服器端TIME_WAIT
,完全相同的連接埠對上的連線可以立即成功地重新建立,而對於客戶端TIME-WAIT
,在第二次迭代時connect()
就會失敗
總而言之,問題有二:
- 伺服器端
TIME_WAIT
真的什麼都不做,只是因為RFC
需要而保持這種狀態嗎? - 建議客戶端啟動 close() 的原因是因為伺服器
TIME_WAIT
沒用嗎?
答案1
在傳輸控制協定這裡的術語伺服器端是指套接字處於 LISTEN 狀態的主機。
RFC1122允許處於 TIME-WAIT 狀態的套接字在某些條件下接受新連接
When a connection is closed actively, it MUST linger in TIME-WAIT state for a time 2xMSL (Maximum Segment Lifetime). However, it MAY accept a new SYN from the remote TCP to reopen the connection directly from TIME-WAIT state, if it:
有關條件的具體詳情,請參閱RFC1122。我希望套接字上也必須有一個匹配的被動開啟(套接字處於偵聽狀態)。
Active OPEN(客戶端連線呼叫)沒有這樣的異常,並且當套接字處於 TIME-WAIT 時必須給出錯誤,根據RFC793。
我對客戶端(在TCP 術語中,執行主動開啟即連接的主機)啟動關閉的建議的猜測與您的建議大致相同,在常見情況下,它將TIME-WAIT 套接字傳播到更多主機上,這些主機有豐富的資源插座。在常見情況下,用戶端不會傳送會在伺服器上重複使用 TIME-WAIT 套接字的 SYN。我同意應用此類建議仍然取決於用例。
答案2
客戶端將根據某種演算法使用新的TCP ISN(初始序號)(大約每4 微秒增加1),而ISN 基本上總是大於在最後一個相同的「ip:port 對」TCP 套接字中傳送的序號FIN,因此即使「ip:portpair」在伺服器上仍然記錄在TIME_WAIT狀態,伺服器也將始終接受新的SYN。
RFC 793 [RFC0793] suggests that the choice of the ISN of a connection
is not arbitrary, but aims to reduce the chances of a stale segment
from being accepted by a new incarnation of a previous connection.
RFC 793 [RFC0793] suggests the use of a global 32-bit ISN generator
that is incremented by 1 roughly every 4 microseconds.
答案3
這可能是 TIME-WAIT 實際用途以及更重要的是它為何如此重要的最清晰示例。它還解釋了為什麼要避免 Linux 機器上的一些「專家」提示來「減少」TIME-WAIT。
答案4
使用不可靠的協議,您永遠無法確定您是否已收到來自對等設備的最後一條訊息,因此假設您的對等設備突然掛斷電話是危險的。 TCP協定的一個主要缺點是只能同時開啟65000個左右的連接埠。但克服這個問題的方法是遷移到伺服器場,它可以更好地隨負載擴展,而不是快速回收連接埠號碼。在客戶端,如果它是基本工作站,則不太可能耗盡連接埠。