在進行TCP高併發服務器開發時,有些規則彷彿是約定俗成的,不少朋友會依據這些規則去作,好比高併發TCP服務器中進行主動關閉的一方最好是客戶端、服務器端程序最好啓用SO_REUSEADDR選項,可是不少人殊不知因此然,咱們爲何要這麼作呢?編程
先上圖服務器
能夠看到執行主動關閉端和被動關閉端的各個階段的狀態,今天咱的重點就是TIME_WAIT狀態,能夠看出TIME_WAIT狀態是執行主動關閉的那一端產生的。網絡
TIME_WAIT狀態有兩個存在的理由併發
可靠地實現TCP全雙工鏈接的終止;ide
容許老的重複分節在網絡中消逝;高併發
第一個理由參考上圖。 假設主動關閉端最終發送的ACK丟失了。對端將從新發送FIN,主動關閉端只有在維護狀態信息的狀況下才能夠從新發送最終的那個ACK。若是不維護這個狀態信息,主動關閉端將會響應一個RST,對端會將此響應標記爲錯誤,因此不能進行正常的關閉。blog
第二個理由假設咱們在ip A:端口B主機和ip C:端口D主機之間創建一個TCP鏈接。咱們關閉這個鏈接,過一段時間在相同的IP地址和端口之間創建另外一個鏈接。因爲他們的IP地址和端口號都相同,因此若是上一個鏈接的老的重複分組再出現會影響新的鏈接。爲了作到這一點,TCP將不會給處於TIME_WAIT狀態的鏈接發起這個新的鏈接。這個持續時間若是大於MSL(IP數據報在因特網中的最大生存時間)ip
若是要知足以上實現,TIME_WAIT狀態必需要有必定的持續時間,因此TIME_WAIT也被稱爲2MSL等待狀態,通常持續時間在1分鐘到4分鐘之間。資源
高併發TCP服務器中進行主動關閉的一方最好是客戶端:由於對於高併發服務器來講文件描述符資源是很重要的資源,若是對於每個鏈接都要經歷TIME_WAIT這個2MSL的時長,勢必形成資源不能立馬複用的浪費。雖然對於客戶端來講TIME_WAIT狀態會佔用端口和句柄資源,可是客戶端通常不多有併發資源限制,因此客戶端執行主動關閉是比較合適的。服務器開發
服務器端程序最好啓用SO_REUSEADDR選項:咱們想這樣作一種狀況,若是生產環境中服務端程序因爲某種錯誤操做關閉了,咱們確定是要立馬重啓服務程序,可是TIME_WAIT還在佔用着這些地址端口資源讓你的服務起不來,那你着不着急。SOREUSEADDR這個選項正是容許地址端口的重複綁定。
參考書籍: