[英]Understanding BSD interface
我試圖了解 BSD 套接字接口中的事件如何轉換為 TCP 連接的 state。 特別是,我試圖了解在連接過程的哪個階段accept()
在服務器端返回
accept()
在哪一個步驟中返回?
連接完成時accept
返回。 客戶端發送他的 ACK 后連接完成。
accept
給你一個可以通信的套接字。 當然你知道,在建立連接之前你不能通信。 並且在握手之前無法建立連接。
在客戶端感知到他的 ACK 之前返回是沒有意義的。 在最初的 SYN 之后,他完全有可能不會說任何話。
kernel 中的 TCP/IP 堆棧代碼通常 [1] 完全完成三次握手,無需任何用戶空間代碼的干預。 您列出的三個步驟都發生在accept()
返回之前。 事實上,它們可能發生在accept()
甚至被調用之前!
當您告訴堆棧為特定 TCP 端口上的連接listen()
時,您傳遞了一個backlog
參數,該參數告訴 kernel 它可以代表您的程序一次靜默接受多少個連接。 當 kernel 自動接受新的連接請求時,正在使用這個隊列,並且它們一直保留在那里,直到您的程序開始accept()
它們。 當您調用accept()
時,當偵聽積壓隊列中有一個或多個連接時,所發生的一切就是從隊列中刪除最舊的連接並綁定到一個新的套接字。 [2]
換句話說,如果您的程序調用listen(sd, 5)
,然后進入一個無限的無操作循環,因此它永遠不會調用accept()
,從客戶端的角度來看,五個並發的客戶端連接請求將成功。 第六個連接請求將在第一個 SYN 數據包上停止,直到擁有 TCP 端口的程序調用accept()
或其他客戶端之一斷開其連接。
[1] 當然,防火牆和其他堆棧修改可以改變這種行為。 我在這里只說默認的 BSD sockets 堆棧行為。
[2] 如果在調用accept()
時沒有等待在 backlog 中的連接,它默認阻塞,除非偵聽器套接字設置為非阻塞,在這種情況下它返回 -1 並且errno
是EWOULDBLOCK
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.