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