Linux TCP socket 開發中 listen backlog 的含義

TCP socket 服務開發的4個步驟 socket->bind->listen->accept
調用listen函數時,有一個backlog參數.html

int listen(int sockfd, int backlog);linux

FreeBSD 和 Linux的實現有些不一樣, 本文討論Linux.
在Linux中backlog表示已完成(ESTABLISHED)且未accept的隊列大小.git

TCP鏈接建立過程
服務器收到客戶端SYN包,發送SYN+ACK包後,在內存建立一個狀態爲SYN_RCVD 的鏈接,放入未完成隊列,這個隊列的大小可經過/proc/sys/net/ipv4/tcp_max_syn_backlog設置.github

服務器收到客戶端的ACK包後,該鏈接的狀態由SYN_RCVD改成ESTABLISHED,並移到已完成隊列.
服務器程序調用accept後,該鏈接移除已完成隊列, 由內核交給程序控制.服務器

TCP 三次握手在應用程序accept以前由內核完成. 應用程序調用accept只是獲取已經完成的鏈接.cookie

已完成隊列滿後
一般未完成隊列的長度大於已完成隊列.
已完成隊列滿後, 當服務器收到來自客戶端的ACK包時
若是 /proc/sys/net/ipv4/tcp_abort_on_overflow 設爲 1, 直接回RST包,結束鏈接.
不然忽視ACK包.
內核有定時器管理未完成隊列,對於因爲網絡緣由沒收到ACK包或是收到ACK包後被忽視的SYN_RCVD鏈接重發SYN+ACK包, 最多重發次數由/proc/sys/net/ipv4/tcp_synack_retries 設定.網絡

backlog 即上述已完成隊列的大小, 這個設置是個參考值,不是精確值. 內核會作些調整, 大於/proc/sys/net/core/somaxconn, 則取somaxconn的值socket

未完成隊列滿後
若是啓用syncookies (net.ipv4.tcp_syncookies = 1),新的鏈接不進入未完成隊列,不受影響.
不然,服務器不在接受新的鏈接.tcp

SYN 洪水攻擊(syn flood attack)
經過僞造IP向服務器發送SYN包,塞滿服務器的未完成隊列,服務器發送SYN+ACK包 沒回復,反覆SYN+ACK包,使服務器不可用.函數

啓用syncookies 是簡單有效的抵禦措施.
啓用syncookies,僅未完成隊列滿後才生效.

參考:
http://veithen.github.io/2014/01/01/how-tcp-backlog-works-in-linux.html
http://blog.dubbelboer.com/2012/04/09/syn-cookies.html
http://blog.csdn.net/justlinux2010/article/details/8604676

相關文章
相關標籤/搜索