1. 程式人生 > >LwIP tcp/ip socket程式設計listen函式分析

LwIP tcp/ip socket程式設計listen函式分析

函式原型為:
int listen(int  sockfd, int  backlog); <span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">//成功返回0,失敗返回-1</span>


下面只討論TCP  UDP不做討論(很少使用到listen函式)
用法:函式應該在呼叫socket和bind這兩個函式之後,accept函式之前呼叫。
作用:讓伺服器套接字sockfd進於監聽狀態。


引數:
      sockfd:套接字,成功返回後進入監聽模式,當有新連線並accept後會再建立一個套接字儲存新的連線
      backlog:暫且翻譯為後備連線吧!下面詳細介紹此引數:
1  當TCP接收一個連線後(三次握手通過)會將此連線存在連線請求佇列裡面,並對佇列個數+1,而backlog為佇列的最大個數,超過此值,則直接將新的連線刪除,即不在接收新的連線。將這些處於請求佇列裡面的連線暫記為後備連線
2  當應用層呼叫accept接收一個連線(處於請求佇列裡面的後備連線),佇列個數會-1。
3  很明顯backlog並不能限制連線的個數,只能限制後備連線的個數。那為啥要用這個backlog呢?主要用於併發處理。
4  backlog的取值範圍 ,一般為0-5,LwIP中在sockets.c中 對backlog進行了過濾:backlog = LWIP_MIN(LWIP_MAX(backlog,0), 0xff);即限制在0-0xff,但是在底層實現時tcp.c中有如下語句:lpcb->backlog = (backlog ? backlog : 1);即最小值為1,所以backlog在LwIP中的取值範圍為1-0xff。


問題來了,既然backlog不能限制連線個數,特別是處於後備的連線也會接受資料,從而浪費資源,而且對方來連線伺服器時顯示連線成功(通過三次握手),但是不能正常服務。那該如何限制呢?下面介紹3種方法:
1 我只呼叫一次accept,讓其他連線處於後備連線,這樣就像上面說的那樣,會浪費資源,且讓連線端(客戶端)很迷茫;
2 可以通過修改 巨集MEMP_NUM_NETCONN的值,此值限定套接字最大個數(所有的)。這樣有個弊端,比如我有兩個伺服器一個想要2個連線  而另一個想要3個連線,這樣就不行了。而且這時我有另一個tcp客戶端的應用,它也要佔用一個socket,也會出現問題;
3  我們可以關閉處於監聽狀態的sock。假設我想限制3個連線,在應用層每當accept到一個連線時可以+1,當判斷有三個連線時關閉sock。然後動態的檢測當前的計數值,當小於3時,再開啟此sock,當然這樣操作必須使能SO_REUSEPORT(允許重用本地地址),可以通過呼叫setsockopt函式來使能