listen()和accept()函数:让套接字进入监听状态并响应客户端请求
對于服務器端程序,使用 bind() 綁定套接字后,還需要使用 listen() 函數讓套接字進入被動監聽狀態,再調用 accept() 函數,就可以隨時響應客戶端的請求了。
listen() 函數
通過 listen() 函數可以讓套接字進入被動監聽狀態,它的原型為:
sock 為需要進入監聽狀態的套接字,backlog 為請求隊列的最大長度。
所謂被動監聽,是指當沒有客戶端請求時,套接字處于“睡眠”狀態,只有當接收到客戶端請求時,套接字才會被“喚醒”來響應請求。
請求隊列
當套接字正在處理客戶端請求時,如果有新的請求進來,套接字是沒法處理的,只能把它放進緩沖區,待當前請求處理完畢后,再從緩沖區中讀取出來處理。如果不斷有新的請求進來,它們就按照先后順序在緩沖區中排隊,直到緩沖區滿。這個緩沖區,就稱為請求隊列(Request Queue)。
緩沖區的長度(能存放多少個客戶端請求)可以通過 listen() 函數的 backlog 參數指定,但究竟為多少并沒有什么標準,可以根據你的需求來定,并發量小的話可以是10或者20。
如果將 backlog 的值設置為?SOMAXCONN,就由系統來決定請求隊列長度,這個值一般比較大,可能是幾百,或者更多。
當請求隊列滿時,就不再接收新的請求,對于 Linux,客戶端會收到 ECONNREFUSED 錯誤,對于 Windows,客戶端會收到?WSAECONNREFUSED 錯誤。
注意:listen() 只是讓套接字處于監聽狀態,并沒有接收請求。接收請求需要使用 accept() 函數。
accept() 函數
當套接字處于監聽狀態時,可以通過 accept() 函數來接收客戶端請求。它的原型為:
它的參數與 listen() 和 connect() 是相同的:sock 為服務器端套接字,addr 為 sockaddr_in 結構體變量,addrlen 為參數 addr 的長度,可由 sizeof() 求得。
accept() 返回一個新的套接字來和客戶端通信,addr 保存了客戶端的IP地址和端口號,而 sock 是服務器端的套接字,大家注意區分。后面和客戶端通信時,要使用這個新生成的套接字,而不是原來服務器端的套接字。
最后需要說明的是:listen() 只是讓套接字進入監聽狀態,并沒有真正接收客戶端請求,listen() 后面的代碼會繼續執行,直到遇到 accept()。accept() 會阻塞程序執行(后面代碼不能被執行),直到有新的請求到來。
總結
以上是生活随笔為你收集整理的listen()和accept()函数:让套接字进入监听状态并响应客户端请求的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 反编译后怎么修改服务器地址,反编译后怎么
- 下一篇: send()/recv()和write(