摘要:listen函數使用主動連接套接口變為被連接套接口,使得一個進程可以接受其它進程的請求,從而成為一個服務器進程。在TCP服務器編程中listen函數把進程變為一個服務器,並指定相應的套接字變為被動連接。
listen函數在一般在調用bind之后-調用accept之前調用,它的函數原型是:
int listen(int sockfd, int backlog)
返回:0──成功, -1──失敗
- 參數sockfd
- 被listen函數作用的套接字,sockfd之前由socket函數返回。在被socket函數返回的套接字fd之時,它是一個主動連接的套接字,也就是此時系統假設用戶會對這個套接字調用connect函數,期待它主動與其它進程連接,然后在服務器編程中,用戶希望這個套接字可以接受外來的連接請求,也就是被動等待用戶來連接。由於系統默認時認為一個套接字是主動連接的,所以需要通過某種方式來告訴系統,用戶進程通過系統調用listen來完成這件事。
- 參數backlog
- 這個參數涉及到一些網絡的細節。在進程正理一個一個連接請求的時候,可能還存在其它的連接請求。因為TCP連接是一個過程,所以可能存在一種半連接的狀態,有時由於同時嘗試連接的用戶過多,使得服務器進程無法快速地完成連接請求。如果這個情況出現了,服務器進程希望內核如何處理呢?內核會在自己的進程空間里維護一個隊列以跟蹤這些完成的連接但服務器進程還沒有接手處理或正在進行的連接,這樣的一個隊列內核不可能讓其任意大,所以必須有一個大小的上限。這個backlog告訴內核使用這個數值作為上限。
- 毫無疑問,服務器進程不能隨便指定一個數值,內核有一個許可的范圍。這個范圍是實現相關的。很難有某種統一,一般這個值會小30以內。
當調用listen之后,服務器進程就可以調用accept來接受一個外來的請求。關於accept更的信息,請接着關注本系統文章。
下面是來自於(http://blog.csdn.net/forrest_chen/article/details/7021409)的一段話:
TCP的服務器端socket基本流程socket->bind->listen->accept->send/recv->closesocket,客戶端基本流程socket->[bind->]->connect->send/recv->closesocket,其中客戶端connect函數應該是和服務器端的listen函數相互作用,而不是accept函數。在listen函數中的第二個參數backlog代表着等待處理的連接隊列(以下簡稱隊列)的長度,神馬意思?我也不太懂,但是通過代碼實踐,我可以簡單的說,每當有一個客戶端connect了,listen的隊列中就加入一個連接,每當服務器端accept了,就從listen的隊列中取出一個連接,轉成一個專門用來傳輸數據的socket(accept函數的返回值),所以在服務器端程序中有兩個socket,前者是用來接收客戶端連接的socket...