1. 程式人生 > >Linux網路程式設計---解決TIME_WAIT狀態引起的bind失敗的方法

Linux網路程式設計---解決TIME_WAIT狀態引起的bind失敗的方法

好幾天都沒寫部落格了,感覺落後了別人一大截,今天趕緊來補補。廢話不多說,直接進入正題。

首先我們得明白,有些情況下,在server的TCP連線沒有完全斷開之前是不允許重新監聽可能是不合理的
例如:

  • 伺服器需要處理非常大量的客戶端的連線(每個連線的生存時間可能很短, 但是每秒都有很大數量的客戶端來請求). 這個時候如果由伺服器端主動關閉連線(比如某些客戶端不活躍, 就需要被伺服器端主動清理掉), 這時服務端就會產生大量TIME_WAIT連線.
  • 由於我們的請求量很⼤大, 就可能導致TIME_WAIT的連線數很多, 導致伺服器的埠不夠用, 無法處理新的連線.

Time_Wait狀態

我們之前在講TCP三次握手和四次揮手的時候,主動關閉連線的一方會進入Time_Wait狀態。但有時侯在非正常的情況下,哪一方的程序退出,也是會導致連線關閉的,這時主動方如果是客戶端主動關閉連線,那麼他會進入Time_Wait狀態,讓他等一會是沒什麼影響的。但通常情況下,我們的伺服器應該是7*24小時不間斷工作的,想想百度或騰訊的伺服器,它要每天處理大量的客戶端的請求,如果某時刻由於某種原因掛掉了,那麼這時伺服器就會進入Time_Wait 狀態,這個時伺服器在Time_Wait的狀態是不可以重啟的,因為它雖然準備關閉了,但還是沒有進行完四次揮手,也就是說他還佔用著之前的埠,所以重啟是起不來的。那在Time_Wait狀態的這段時間內,肯定會有大量的客戶端的請求會發給服務端,但是這段時間是不能處理這些請求的,那這將會給公司造成不可預測的損失,想想雙11阿里的伺服器掛了,如果不處理,在Time_Wait(Linux下1個msl是60秒)這短短120秒,會損失多少?那應該怎麼處理?

解決辦法

借用函式setsockopt

 #include <sys/types.h>          /* See NOTES */
 #include <sys/socket.h>
 
int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);

sockfd:標識一個套介面的描述字。
level:選項定義的層次;支援SOL_SOCKET、IPPROTO_TCP、IPPROTO_IP和IPPROTO_IPV6。
optname:需設定的選項。
optval:指標,指向存放選項待設定的新值的緩衝區。
optlen:optval緩衝區長度。

在server程式碼的socket()和bind()呼叫之間插入如下程式碼:

int opt = 1setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

這樣當伺服器突然掛了,就可以立即重啟伺服器。來處理請求。