TCP建立連接配接是要進行三次握手,但是否完成三次握手後,伺服器就處理(accept)呢?
backlog其實是一個連接配接隊列,在Linux核心2.2之前,backlog大小包括半連接配接狀态和全連接配接狀态兩種隊列大小。
半連接配接狀态為:伺服器處于Listen狀态時收到用戶端SYN封包時放入半連接配接隊列中,即SYN queue(伺服器端口狀态為:SYN_RCVD)。
全連接配接狀态為:TCP的連接配接狀态從伺服器(SYN+ACK)響應用戶端後,到用戶端的ACK封包到達伺服器之前,則一直保留在半連接配接狀态中;當伺服器接收到用戶端的ACK封包後,該條目将從半連接配接隊列搬到全連接配接隊列尾部,即 accept queue (伺服器端口狀态為:ESTABLISHED)。
在Linux核心2.2之後,分離為兩個backlog來分别限制半連接配接(SYN_RCVD狀态)隊列大小和全連接配接(ESTABLISHED狀态)隊列大小。
SYN queue 隊列長度由 /proc/sys/net/ipv4/tcp_max_syn_backlog 指定,預設為2048。
Accept queue 隊列長度由 /proc/sys/net/core/somaxconn 和使用listen函數時傳入的參數,二者取最小值。預設為128。在Linux核心2.4.25之前,是寫死在代碼常量 SOMAXCONN ,在Linux核心2.4.25之後,在配置檔案 /proc/sys/net/core/somaxconn 中直接修改,或者在 /etc/sysctl.conf 中配置 net.core.somaxconn = 128 。

可以通過ss指令來顯示
在LISTEN狀态,其中 Send-Q 即為Accept queue的最大值,Recv-Q 則表示Accept queue中等待被伺服器accept()。
另外用戶端connect()傳回不代表TCP連接配接建立成功,有可能此時accept queue 已滿,系統會直接丢棄後續ACK請求;用戶端誤以為連接配接已建立,開始調用等待至逾時;伺服器則等待ACK逾時,會重傳SYN+ACK 給用戶端,重傳次數受限 net.ipv4.tcp_synack_retries ,預設為5,表示重發5次,每次等待30~40秒,即半連接配接預設時間大約為180秒,該參數可以在tcp被洪水攻擊是臨時啟用這個參數。
檢視SYN queue 溢出
檢視Accept queue 溢出
參考資料:
<a href="http://www.cnxct.com/something-about-phpfpm-s-backlog/" target="_blank">TCP SOCKET中backlog參數的用途是什麼?</a>
<a href="http://www.2cto.com/net/201307/224634.html" target="_blank">TCP/IP協定中backlog分析與設定以及TCP狀态變化</a>
<a href="http://jaseywang.me/2014/07/20/tcp-queue-%E7%9A%84%E4%B8%80%E4%BA%9B%E9%97%AE%E9%A2%98/" target="_blank">TCP queue 的一些問題</a>
<a href="http://www.2cto.com/Article/201309/241096.html" target="_blank">TCP洪水攻擊(SYN Flood)的診斷和處理</a>
本文轉自1清風攬月1 51CTO部落格,原文連結:http://blog.51cto.com/watchmen/1975570,如需轉載請自行聯系原作者