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