關(guān)于TCP全連接隊(duì)列和半連接隊(duì)列
在TCP的三次握手中存在著兩個(gè)隊(duì)列、backlog、tcp_abort_on_overflow等概念知識(shí)點(diǎn)。常見的連接服務(wù)異常有很多,如Connection refused等問題。通過對(duì)這些知識(shí)的理解有助于結(jié)合一些排查手段有效地解決一些生產(chǎn)上出現(xiàn)的連接服務(wù)異常問題。下面將對(duì)這些進(jìn)行討論分析。
一、TCP三次握手
握手過程:
- 第一次:client發(fā)送syn到server進(jìn)行握手
- 第二次:server收到syn后回復(fù)syn+ack給client同時(shí)服務(wù)端將相關(guān)信息放在半連接隊(duì)列中。
- 第三次:client收到syn+ack后回復(fù)server一個(gè)ack,表示收到了server的syn+ack,server收到client的ack后將更具不同的情況進(jìn)行不同的處理(這與tcp_abort_on_overflow參數(shù)和accept queue全連接隊(duì)列是否已滿有關(guān))
三次握手中Socket狀態(tài)枚舉:
- LISTEN:偵聽來自遠(yuǎn)方TCP端口的連接請(qǐng)求
- SYN-SENT:在發(fā)送連接請(qǐng)求后等待匹配的連接請(qǐng)求
- SYN-RECEIVED:在收到和發(fā)送一個(gè)連接請(qǐng)求后等待對(duì)連接請(qǐng)求的確認(rèn)
- ESTABLISHED:代表一個(gè)打開的連接,數(shù)據(jù)可以傳送給用戶
二、全連接隊(duì)列和半連接隊(duì)列
在握手階段存在兩個(gè)隊(duì)列:
- 全連接隊(duì)列(accept queue)
- 半連接隊(duì)列(syns queue)
解析:當(dāng)?shù)谝淮挝帐?client客戶端的SYN到達(dá)server服務(wù)端時(shí))TCP會(huì)在未完成連接隊(duì)列中創(chuàng)建一個(gè)新項(xiàng),這一項(xiàng)會(huì)一直保留在未完成連接隊(duì)列中直到第三次握手(客戶對(duì)服務(wù)器SYN的ACK)結(jié)束為止。如果三次握手全部正常完成,該項(xiàng)則會(huì)從未完成連接隊(duì)列移到已完成連接隊(duì)列的隊(duì)尾。當(dāng)進(jìn)程調(diào)用accept()時(shí),已完成連接隊(duì)列中的隊(duì)頭項(xiàng)將返回給進(jìn)程。
三、第三次握手時(shí)server具體的處理方式

場(chǎng)景1:當(dāng)全連接未滿
當(dāng)server收到client的ack后會(huì)先判斷全連接隊(duì)列accept queue是否已滿,如果隊(duì)列未滿則從半連接隊(duì)列拿出相關(guān)信息存放入全連接隊(duì)列中,之后服務(wù)端accept()處理此請(qǐng)求。
場(chǎng)景2:當(dāng)全連接已滿且tcp_abort_on_overflow = 0
server會(huì)扔掉client 發(fā)過來的ack。之后隔一段時(shí)間server會(huì)重發(fā)握手第二步的syn+ack包給client,如果客戶端連接一直排隊(duì)不上等待超時(shí)則會(huì)報(bào)超時(shí)異常。
場(chǎng)景3:全連接已滿且tcp_abort_on_overflow = 1時(shí)
server會(huì)發(fā)送一個(gè)reset包給client,表示廢除這個(gè)握手過程和這個(gè)連接(客戶端會(huì)報(bào)connection reset by peer異常)
四、關(guān)于backlog
backlog表示全連接隊(duì)列(已連接未處理隊(duì)列)的大小,該值默認(rèn)為50。

當(dāng)全連接隊(duì)列滿時(shí)則會(huì)根據(jù)tcp_abort_on_overflow的值做出相應(yīng)的處理方式
- //Linux查看tcp_abort_on_overflow值
- cat /proc/sys/net/ipv4/tcp_abort_on_overflow
五、總結(jié)
TCP存在兩個(gè)隊(duì)列(全連接隊(duì)列和半連接隊(duì)列),第一次握手后TCP會(huì)產(chǎn)生的新項(xiàng)并先存放到半連接隊(duì)列中。當(dāng)完成三次握手之后項(xiàng)會(huì)移動(dòng)到全連接隊(duì)列里(全連接隊(duì)列默認(rèn)大小backlog值是50)。如果當(dāng)全連接隊(duì)列滿了server則會(huì)根據(jù)tcp_abort_on_overflow 的值來做對(duì)應(yīng)的處理,,值為0則丟棄當(dāng)前客戶端的ack,值為1則廢棄當(dāng)前握手過程與連接。

























