在進行TCP高并發伺服器開發時,有些規則仿佛是約定俗成的,很多朋友會依據這些規則去做,比如高并發TCP伺服器中進行主動關閉的一方最好是用戶端、伺服器端程式最好啟用SO_REUSEADDR選項,但是很多人卻不知是以然,我們為什麼要這麼做呢?
先上圖
<a target="_blank" href="http://blog.51cto.com/attachment/201312/203639589.jpg"></a>
可以看到執行主動關閉端和被動關閉端的各個階段的狀态,今天咱的重點就是TIME_WAIT狀态,可以看出TIME_WAIT狀态是執行主動關閉的那一端産生的。
TIME_WAIT狀态有兩個存在的理由
可靠地實作TCP全雙工連接配接的終止;
允許老的重複分節在網絡中消逝;
第一個理由參考上圖。 假設主動關閉端最終發送的ACK丢失了。對端将重新發送FIN,主動關閉端隻有在維護狀态資訊的情況下才可以重新發送最終的那個ACK。如果不維護這個狀态資訊,主動關閉端将會響應一個RST,對端會将此響應标記為錯誤,是以不能進行正常的關閉。
第二個理由假設我們在ip A:端口B主機和ip C:端口D主機之間建立一個TCP連接配接。我們關閉這個連接配接,過一段時間在相同的IP位址和端口之間建立另一個連接配接。由于他們的IP位址和端口号都相同,是以如果上一個連接配接的老的重複分組再出現會影響新的連接配接。為了做到這一點,TCP将不會給處于TIME_WAIT狀态的連接配接發起這個新的連接配接。這個持續時間如果大于MSL(IP資料報在網際網路中的最大生存時間)
如果要滿足以上實作,TIME_WAIT狀态必須要有一定的持續時間,是以TIME_WAIT也被稱為2MSL等待狀态,一般持續時間在1分鐘到4分鐘之間。
高并發TCP伺服器中進行主動關閉的一方最好是用戶端:因為對于高并發伺服器來說檔案描述符資源是很重要的資源,如果對于每一個連接配接都要經曆TIME_WAIT這個2MSL的時長,勢必造成資源不能立馬複用的浪費。雖然對于用戶端來說TIME_WAIT狀态會占用端口和句柄資源,但是用戶端一般很少有并發資源限制,是以用戶端執行主動關閉是比較合适的。
伺服器端程式最好啟用SO_REUSEADDR選項:我們想這樣做一種情況,如果生産環境中服務端程式由于某種錯誤操作關閉了,我們肯定是要立馬重新開機服務程式,但是TIME_WAIT還在占用着這些位址端口資源讓你的服務起不來,那你着不着急。SOREUSEADDR這個選項正是允許位址端口的重複綁定。
參考書籍:
本文轉自永遠的朋友部落格51CTO部落格,原文連結http://blog.51cto.com/yaocoder/1338567如需轉載請自行聯系原作者
yaocoder