Workerman长连接不走三次握手是因为TCP连接持续保持未断开,复用同一socket fd收发数据;所谓“重连”实为外部干扰(如NAT超时、防火墙回收)导致的客户端新连接,与Workerman本身无关。

Workerman 长连接不走重复三次握手,是因为它根本没断开过连接——TCP 连接从 accept() 成功那一刻起就一直保持打开状态,后续所有数据收发都复用这个已建立的 socket 文件描述符。
这和 HTTP 短连接(比如 PHP-FPM 场景)有本质区别:后者每次请求完立刻 close(),下次请求必须重连;而 Workerman 的 Worker 进程在事件循环中持续监听该 socket 上的 read 事件,只要客户端不主动断开、服务端也不调用 $connection->close(),内核就始终认为这个 TCP 连接是 ESTABLISHED 状态。
长连接复用的是同一个 socket fd,不是“新连接”
你看到的“多次请求”,其实是同一 TCP 连接上的多段应用层数据流。Workerman 不会为每个请求新建 socket,也不会触发 connect() 或 accept()。它的事件循环只做两件事:read() 数据进来时解析协议,write() 数据出去时推送到已就绪的 socket 缓冲区。
- 客户端发完第一个消息后不关连接 → socket 仍处于 ESTABLISHED
- 客户端隔 2 秒再发第二个消息 → 内核直接走已有连接路径,跳过 SYN/SYN-ACK/ACK
- Workerman 的
onMessage回调被触发两次,但底层 fd 没变过
为什么有时候看起来像“重连”?
这不是 Workerman 的行为,而是外部干扰导致连接中断后被迫重连:
- NAT 设备超时(常见于家用路由器),5~10 分钟无流量自动踢掉连接
- 防火墙或云厂商 SLB 主动回收空闲连接(如阿里云默认 900 秒)
- 客户端进程崩溃、网络切换(WiFi 切 4G)、休眠唤醒
- 服务端未设心跳或心跳超时未清理,连接卡在半死状态
这种“断了再连”才需要三次握手 —— 但那是客户端发起的新连接,和 Workerman 是否支持长连接无关。
Workerman 本身不干预 TCP 状态,只响应内核通知
Workerman 的角色是用户态事件驱动框架,它不控制 TCP 状态机,只依赖内核通过 epoll_wait()(或 select)返回的就绪事件。只要内核还把那个 fd 标记为可读/可写,Workerman 就继续用它。
- 如果客户端静默断电,服务端不会立刻知道,得靠心跳超时检测
- 如果客户端发了 FIN,内核通知
read()返回 0,Workerman 才触发onClose - 没有心跳机制时,“连接还在”只是假象,实际可能已被中间设备掐断

















