TCP 半连接队列和全连接队列有什么区别?backlog 满了会发生什么?
下面是一段教学用的模拟面试。
🧑💻 面试官: TCP 半连接队列和全连接队列有什么区别?
🙋♂️ 我: 一个放没连好的,一个放连好的。
🧑💻 面试官: 握手已经完成,应用还没 accept,这条连接在哪?listen 的 backlog 主要限制哪个队列?
🙋♂️ 我: 在等待 accept 的队列里,Linux 的 backlog 主要管这个队列。
🧑💻 面试官: 那你看到连接失败,只把 backlog 调大,能解决握手洪峰和应用处理不过来两种问题吗?
先找请求卡在哪一段:「握手进行中」,还是「握手完成、等待应用接走」。两个拥堵点不一样。
面试速答(60 秒版)
以现代 Linux 的 TCP 监听为例,半连接队列通常用于管理握手尚未完成的请求;全连接队列保存已经建立、等待应用 accept 的连接。
listen 的 backlog 主要表达已完成连接队列的长度要求,还会受系统 somaxconn 等配置限制。半连接相关限制则有 tcp_max_syn_backlog 等条件,启用 SYN cookies 时行为还要另外看。
全连接队列积压,可能与应用 accept 不及时、负载突增等有关;半连接压力则要检查握手速度、网络和攻击等因素。
队列只是缓冲,不增加应用持续处理能力。溢出后的行为也受系统参数和实际路径影响,不能一概说一定立即返回 RST。

图:握手中,还是等 accept?。
知识点详解:握手完成了,为什么还没交给应用?
两个队列对应两个等待阶段
客户端发起连接后,服务端还要完成 TCP 握手。在这段过程中,服务端需要管理尚未完成建立的请求。
握手完成后,连接已经建立,但应用不一定马上调用 accept 把它取走。这些等待应用接收的连接,进入已完成连接队列。
所以,“全连接队列里有数据”不表示 HTTP 请求已经处理完成。这里说的是连接建立状态,不是业务处理进度。
backlog 为什么不能直接理解成所有连接总数?
现代 Linux 的 listen backlog 主要关联等待 accept 的已完成队列,并受系统上限约束。它不是“服务器总共最多能维持几个连接”,也不是应用线程池大小。
历史与系统实现可能不同。面试回答要先说明平台,Linux 的解释可以核对 listen(2) Notes。
半连接相关参数与 SYN cookies 等机制,还要查对应内核和配置。不能只调整一个数字,就认为握手、等待和已接受连接都统一被扩大。

图:backlog 主要管等待 accept。
应用 accept 不及时,会发生什么?
假设连接快速建立,而应用因为调度、工作方式或资源压力,没能及时取走它们。已完成队列就会积压。
增大队列可以承受一些短时波动,但如果持续进入速度大于处理速度,更大的队列只是让等待更久,最终仍会遇到容量问题。
这里还要区分 accept 速度和接受之后的请求处理能力。应用可能很快取走连接,却在业务层形成另一条队列。不能只看监听队列空了就说服务健康。
半连接压力要怎样判断?
如果很多请求停在握手阶段,要检查网络丢包、往返时延、客户端行为与 SYN 流量等因素。
SYN cookies 在相关条件下帮助减轻某类资源压力,但不是免费解决所有攻击和网络问题。实际诊断要结合系统计数、抓包和连接状态,不把一个机制名字当成结论。
溢出不只有一种结果
队列满时,重传、忽略或关闭等行为可能受配置和当前协议阶段影响。用户看到的是连接变慢、超时或失败,不应反推一定发生了某一种固定内核动作。
验证时应记录目标内核、监听配置、计数变化和抓包证据。本文解释机制,没有把假设流量写成生产观测值。

图:队列变长,不增加处理速度。
面试官继续追问
调大队列为什么可能让体验更差?
持续过载时,请求等得更久才失败,资源占用也可能增加。队列长度需要与可接受等待时间、拒绝策略一起设计。
应该先看什么证据?
先定位握手阶段还是等待 accept,再检查相应队列、系统上限、溢出计数与应用行为,不只看总连接数。
面试速记卡
- 半连接:握手尚未完成的请求。
- 全连接:握手完成,等待应用 accept。
- Linux backlog:主要针对等待 accept 的队列,受系统上限约束。
- 容量:队列缓冲波动,不增加持续处理能力。
- 溢出:按阶段、内核与配置判断,不背固定 RST 结论。
公司面试真题
这道题暂未收录可核验的公司真题来源。你可以先阅读本文解析,或浏览已收录的公司面试真题。
浏览公司面试真题 →