重学TCP协议(9) 半连接队列、全连接队列
1. 半連接隊列、全連接隊列基本概念
1.1 tcp_abort_on_overflow
- tcp_abort_on_overflow 為 0 表示三次握手最后一步全連接隊列滿以后 server 會丟掉 client 發過來的 ACK,服務端隨后會進行重傳 SYN+ACK。
- tcp_abort_on_overflow 為 1 表示全連接隊列滿以后服務端直接發送 RST 給客戶端。
1.2 ss 命令
ss 命令可以查看全連接隊列的大小和當前等待 accept 的連接個數,執行 ss -lnt 即可
ss -lnt | grep :9090 State Recv-Q Send-Q Local Address:Port Peer Address:Port LISTEN 51 50 *:9090 *:*Recv-Q 表示 accept 隊列排隊的連接個數,Send-Q 表示全連接隊列(也就是 accept 隊列)的總大小。
2. 半連接隊列
2.1 半連接隊列的長度
半連接隊列的大小由3個值決定:
- 用戶層 listen 傳入的backlog
- 系統變量 net.ipv4.tcp_max_syn_backlog,默認值為 128
- 系統變量 net.core.somaxconn,默認值為 128
2.2 半連接隊列長度的計算過程
如果用戶傳入的 backlog 值大于系統變量 net.core.somaxconn 的值,用戶設置的 backlog 不會生效,使用系統變量值,默認為 128。
將上一步計算的backlog值穿給nr_table_entries,sysctl_max_syn_backlog 為 net.ipv4.tcp_max_syn_backlog 的值
- 在 nr_table_entries 與 sysctl_max_syn_backlog 兩者中的較小值,賦值給 nr_table_entries(因為sysctl_max_syn_backlog默認是128,如果沒有修改,產生的最大值就只能是128)
- 在 nr_table_entries 和 8 取較大值,賦值給 nr_table_entries(最小只能是8)
- nr_table_entries + 1 向上取求最接近的最大 2 的指數次冪(保證是2的冪次)
- 通過 for 循環找不大于 nr_table_entries 最接近的 2 的對數值
3.全連接隊列
「全連接隊列」包含了服務端所有完成了三次握手,但是還未被應用調用 accept 取走的連接隊列。此時的 socket 處于 ESTABLISHED 狀態。每次應用調用 accept() 函數會移除隊列頭的連接。如果隊列為空,accept() 通常會阻塞。全連接隊列也被稱為 Accept 隊列。
3.1 全連接隊列的長度
全連接隊列的大小由3個值決定:
- 用戶層 listen 傳入的backlog
- 系統變量 net.core.somaxconn,默認值為 128
3.2 全連接隊列長度的計算過程
全連接隊列的大小是 listen 傳入的 backlog 和 somaxconn 中的較小值。
3.3 全連接隊列溢出的情況
-
如上圖,150166號包是三次握手中的第三步client發送ack給server,然后150167號包中client發送了一個長度為816的包給server。
-
因為在這個時候client認為連接建立成功(因為已經完成三次握手了),但是server上這個連接實際沒有ready(因為全連接隊列已經滿了),所以server直接丟掉client發來的ACK包,并且一段時間后,server認為自己第二次握手的syn+ack包丟包了,因此就重發syn+ack包(SYN+ACK重傳的次數是由操作系統的一個文件決定的/proc/sys/net/ipv4/tcp_synack_retries)
-
一段時間后client又收到了syn+ack包,認為第三次握手的ack丟包了,然后重傳這816個字節的ack包。一直到超時,client主動發fin包斷開該連接。
總結
以上是生活随笔為你收集整理的重学TCP协议(9) 半连接队列、全连接队列的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: leetcode 1720. 解码异或后
- 下一篇: 做梦梦到吃橘子什么意思