函數原型:
int listen(int sockfd, int backlog);
當服務器編程時,經常需要限制客戶端的連接個數,下面為問題分析以及解決辦法:
下面只討論TCP UDP不做討論(很少使用到listen函數)
listen函數用法:函數應該在調用socket和bind這兩個函數之后,accept函數之前調用。
listen函數作用:讓服務器套接字sockfd進入監聽狀態。
1.返回值:
成功返回0;
失敗返回-1。
2.參數:
sockfd:套接字,成功返回后進入監聽模式,當有新連接並accept后會再建立一個套接字保存新的連接;
backlog:暫且翻譯為后備連接吧!下面詳細介紹此參數:
1) 當TCP接收一個連接后(三次握手通過)會將此連接存在連接請求隊列里面,並對隊列個數+1,而backlog為此隊列允許的最大個數,超過此值,則直接將新的連接刪除,即不在接收新的連接。將這些處於請求隊列里面的連接暫記為后備連接,這些都在底層自動完成,底層將連接添加到隊列后等待上層來處理(一般是調用accept函數接收連接);
2) 當上層調用accept函數接收一個連接(處於請求隊列里面的后備連接),隊列個數會-1;
3) 那么這樣一個加一個減,只要底層提交的速度小於上層接收的速度(一般是這樣),很明顯backlog就不能限制連接的個數,只能限制后備連接的個數。那為啥要用這個backlog呢?主要用於並發處理,當上層沒來的及接收時,底層可以提交多個連接;
4) backlog的取值范圍 ,一般為0-5。
3.那么,如何才能限制連接個數,而不是后備的連接個數呢?如下:
我們可以關閉處於監聽狀態的sock。假設我想限制3個連接,在應用層每當accept到一個連接時,定義一個變量var讓其+1,當判斷有三個連接時關閉sock。然后動態的檢測當前的計數值var,當小於3時,再打開此sock,當然這樣操作必須使能SO_REUSEPORT(允許重用本地地址),可以通過調用setsockopt函數來使能,問題解決。