time-wait狀態和reuse問題。上一篇看了tcp的三次握手與四次揮手,記得四次揮手,主動斷開連線的一方最後乙個狀態就是time-wait狀態,並且一定是主動斷開連線的一方,它可能使socket能陷入一種時間比較長的狀態,過多的time-wait會影響新socket的建立。那麼time-wait為什麼會存在?它的作用又是什麼呢?
tcp連線和斷開連線狀態轉換圖:
從上圖可以看到,客戶端連線在收到伺服器的結束報文段(6)之後,並沒有直接進入closed狀態,而是轉移到time-wait狀態。此狀態一般要等待2倍的msl(報文段的最大生存時間)的時間,才能完全關閉。rfc 1122建議值為2min。
time-wait狀態存在的原因有兩點:
可靠地終止tcp連線 確保新tcp連線和老tcp連線不會相互干擾
原因1:可靠地終止tcp連線
其實就是確保「主動關閉」一端最後發出的ack到達「被動關閉「的一端。假如用於確認伺服器結束報文段6的tcp報文段7丟失了,那麼伺服器將會重發結束報文段。而客戶端也就是主動斷開的一端需要停留在某個狀態重複收到結束報文段。假如客戶端傳送完ack報文段後直接進入closed狀態,而最後的ack報文段又丟失了,伺服器程序會不斷重發結束報文段,客戶端則以復位報文段來回應伺服器,伺服器會認為這是個錯誤,因為它現在在等的是ack報文段。
原因2:確保新tcp連線和老tcp連線不會相互干擾
linux下,乙個tcp埠不能被同時開啟兩次以上。當乙個tcp連線處於time-wait狀時,我們將無法立即使用該連線占用的埠來建立乙個新連線。如果不存在time-wait狀態,,應用程式再建立乙個一樣的連線,這時新連線又可能受到舊連線tcp報文段,這顯然是不應該發生。
還有剛說過time-wait狀態會維持2msl的時間,而tcp報文段的最大生存時間是msl,所以確保了網路上傳輸方向上的未被接受的、遲到的tcp報文段都已經消失。這也為什麼要維持2msl時間。
然而有時候我們又希望避免time-wait狀態,當程式退出後我們可以立即重啟它。例如百度騰訊這些大公司,如果真的哪天伺服器崩掉了,必定是需要立即重啟,要不然損失可就大了。
這裡我用自己寫的乙個select伺服器測試,發現先ctrl+c之後,再次重新啟動伺服器,就會出錯,這裡就可以推測出,這裡就是因為處在time-wait狀態,埠被占用著,所以重新啟動失敗。那麼怎麼解決這個問題呢?
上圖可以看到位址已經被用了
那麼我們如何解決這個問題呢?
可以使用使用setsockopt函式
int setsockopt(int sockfd, int level, int optname,
const void *optval, socklen_t optlen);
//可以在socket函式和bind函式之間加入這個函式
int on=1;
setsockopt(lisetn_sock,sol_socket,so_reuseaddr,&on,sizeof(on))
so_reuseaddr是什麼意思呢?
這個套接字通知核心,如果埠忙,而tcp處在time-wait狀態時,可以重用埠。如果埠忙,而tcp不在time-wait,在其他狀態時,仍然會得到乙個錯誤資訊,指明位址已在使用中。
另外so_reuseaddr選項提供的功能:
so_reuseaddr允許啟動乙個監聽伺服器並**其眾所周知埠,即使以前建立的將此埠用做他們的本地埠的連線仍存在。這通常是重啟監聽伺服器時出現,若不設定此選項,則bind時將出錯。 so_reuseaddr允許在同一埠上啟動同一伺服器的多個例項,只要每個例項**乙個不同的本地ip位址即可。對於tcp,我們根本不可能啟動**相同ip位址和相同埠號的多個伺服器。 so_reuseaddr允許單個程序**同一埠到多個套介面上,只要每個**指定不同的本地ip位址即可。這一般不用於tcp伺服器。 so_reuseaddr允許完全重複的**:當乙個ip位址和埠繫結到某個套介面上時,還允許此ip位址和埠**到另乙個套介面上。一般來說,這個特性僅在支援多播的系統上才有,而且只對udp套介面而言(tcp不支援多播)。
TIME WAIT和CLOSE WAIT狀態區別
在伺服器的日常維護過程中,會經常用到下面的命令 plain view plain copy print netstat n awk tcp end netstat n awk tcp end 它會顯示例如下面的資訊 time wait 814 close wait 1 fin wait1 1 est...
TIME WAIT和CLOSE WAIT狀態區別
在伺服器的日常維護過程中,會經常用到下面的命令 netstat n awk tcp end 它會顯示例如下面的資訊 time wait 814 close wait 1 fin wait1 1 established 634 syn recv 2 last ack 1 常用的三個狀態是 establ...
TIME WAIT狀態釋疑
一 現象 登陸伺服器的時候輸入netstat natup 發現存在大量time wait狀態的連線 tcp 0 0 127.0.0.1 3306 127.0.0.1 41378 time wait tcp 0 0 127.0.0.1 3306 127.0.0.1 41379 time wait tc...