socket的listen()的backlog引數和未完成佇列、已完成佇列的關係

yushuifirst發表於2015-05-31

TCP:socket的listen()的backlog引數和未完成佇列、已完成佇列的關係

listen函式是網路程式設計一個基本的函式,而且它的backlog引數卻是和TCP協議息息相關的。我們來看一下一個backlog引數到底有多少祕密。

一、 為了理解backlog引數,我們必須首先認識listen函式。

#include<sys/socket.h>
int listen(int sockfd, int backlog);

listen函式僅由TCP伺服器呼叫,它做兩件事情:

1、當socket函式建立一個套介面時,它被假設為一個主動套裝口,也就是說,它是一個將呼叫connet發起連線的客戶套介面。listen函式把一個未連線的套介面轉換成一個被動套介面,指示核心應接受指向該套介面的連線請求。根據TCP狀態轉換圖,呼叫listen導致套介面從CLOSED狀態轉換到LISTEN狀態。

2、本函式的第二個引數規定了核心應該為相應套介面排隊的最大連線個數。

為了更好的理解backlog引數,我們必須認識到核心為任何一個給定的監聽套介面維護兩個佇列

1、未完成連線佇列(incomplete connection queue),每個這樣的SYN分節對應其中一項:已由某個客戶發出併到達伺服器,而伺服器正在等待完成相應的TCP三路握手過程。這些套介面處於SYN_RCVD狀態。

2、已完成連線佇列(completed connection queue),每個已完成TCP三路握手過程的客戶對應其中一項。這些套介面處於ESTABLISHED狀態

當來自客戶的SYN到達時,TCP在未完成連線佇列中建立一個新項,然後響應以三路握手的第二個分節:伺服器的SYN響應,其中稍帶對客戶SYN的ACK(即SYN+ACK)。這一項一直保留在未完成連線佇列中,直到三路握手的第三個分節(客戶對伺服器SYN的ACK)到達或者該項超時為止(曾經源自Berkeley的實現為這些未完成連線的項設定的超時值為75秒)。如果三路握手正常完成,該項就從未完成連線佇列移到已完成連線佇列的隊尾。當程式呼叫accept時,已完成連線佇列中的隊頭項將返回給程式,或者如果該佇列為空,那麼程式將被投入睡眠,直到TCP在該佇列中放入一項才喚醒它。

相關文章