使用listen 和accept 函式

2021-07-12 07:04:43 字數 1654 閱讀 5753

對於伺服器端程式,使用 bind() 繫結套接字後,還需要使用 listen() 函式讓套接字進入被動監聽狀態,再呼叫 accept() 函式,就可以隨時響應客戶端的請求了。通過 listen() 函式可以讓套接字進入被動監聽狀態,它的原型為:

int

listen

(int sock,

int backlog);

//linux

intlisten

(socket

sock,

int backlog);

//windows

sock 為需要進入監聽狀態的套接字,backlog 為請求佇列的最大長度。

所謂被動監聽,是指當沒有客戶端請求時,套接字處於「睡眠」狀態,只有當接收到客戶端請求時,套接字才會被「喚醒」來響應請求。

請求佇列

當套接字正在處理客戶端請求時,如果有新的請求進來,套接字是沒法處理的,只能把它放進緩衝區,待當前請求處理完畢後,再從緩衝區中讀取出來處理。如果不斷有新的請求進來,它們就按照先後順序在緩衝區中排隊,直到緩衝區滿。這個緩衝區,就稱為

請求佇列(request queue)

。緩衝區的長度(能存放多少個客戶端請求)可以通過 listen() 函式的 backlog 引數指定,但究竟為多少並沒有什麼標準,可以根據你的需求來定,併發量小的話可以是10或者20。

如果將 backlog 的值設定為 

somaxconn

,就由系統來決定請求佇列長度,這個值一般比較大,可能是幾百,或者更多。

當請求佇列滿時,就不再接收新的請求,對於 linux,客戶端會收到 econnrefused 錯誤,對於 windows,客戶端會收到 wsaeconnrefused 錯誤。

注意:listen() 只是讓套接字處於監聽狀態,並沒有接收請求。接收請求需要使用 accept() 函式。當套接字處於監聽狀態時,可以通過 accept() 函式來接收客戶端請求。它的原型為:

int

accept

(int sock,

struct

sockaddr

*addr,

socklen_t

*addrlen);

//linux

socket

accept

(socket

sock,

struct

sockaddr

*addr,

int*addrlen);

//windows

它的引數與 listen() 和 connect() 是相同的:sock 為伺服器端套接字,addr 為 sockaddr_in 結構體變數,addrlen 為引數 addr 的長度,可由 sizeof() 求得。

accept() 返回乙個新的套接字來和客戶端通訊,addr 儲存了客戶端的ip位址和埠號,而 sock 是伺服器端的套接字,大家注意區分。

後面和客戶端通訊時,要使用這個新生成的套接字,而不是原來伺服器端的套接字。

最後需要說明的是:listen() 只是讓套接字進入監聽狀態,並沒有真正接收客戶端請求,listen() 後面的**會繼續執行,直到遇到 accept()。accept() 會阻塞程式執行(後面**不能被執行),直到有新的請求到來。

TCP的listen和accept函式

int listen int sockfd,int backlog 完成兩件事情 1 將未連線的套介面轉換成被動套介面,指示核心應接收指向此套 接的連線請求。導致套介面從closed狀態到listen狀態 2 規定核心為此套介面排隊的最大連線數。一般來講,此函式應該在呼叫了socket bind之後...

tcp listen呼叫和accept呼叫

在看listen的 之前.我們也先來看相關的資料結構 inet connection sock它包含了乙個icsk accept queue的域,這個域是乙個request sock queue型別,我們就先來看這個結構 request sock queue也就表示乙個request sock佇列....

Swoole的push和listen用法

tcp連線迭代器,可以使用foreach遍歷伺服器當前所有的連線,此屬性的功能與swoole server connnection list是一致的,但是更加友好。遍歷的元素為單個連線的fd。注意 connections屬性是乙個迭代器物件,不是php陣列,所以不能用var dump或者陣列下標來訪...