Workerman TCP服务器连接立刻断开的主因是未实现onConnect和onMessage基础逻辑:必须显式定义onConnect(如仅记录日志),onMessage中须调用send()或至少读完数据,否则连接被静默关闭。

Workerman 启动 TCP 服务器后连接立刻断开?
常见现象是客户端 telnet 或自写脚本连上就断,没报错也没日志。根本原因通常是没实现 onConnect 和 onMessage 的基础逻辑,Workerman 默认收到数据后若没处理,会直接 close 连接。
- 必须显式定义
onConnect(哪怕只做日志),否则部分版本会静默拒绝后续通信 -
onMessage必须调用$connection->send()或至少读完数据,否则连接可能被心跳或空闲检测中断 - 别依赖
onClose做关键清理——它不一定触发,尤其客户端异常断网时
text 协议下怎么区分完整消息?
Workerman 不自带粘包/拆包解析,text 协议通常指换行分隔(\n 或 \r\n),但 TCP 是流式传输,一次 onMessage 可能收到多条、半条或跨包消息。
- 用
Worker::$protocol = 'text'仅启用基础换行识别,但要求客户端严格每条消息末尾带\n - 更稳妥的做法是自己在
onMessage中缓存未完成的数据,按\n切分,剩余部分留到下次回调再拼接 - 注意 Windows 客户端可能发
\r\n,Linux 发\n,建议统一用trim($data, "\r\n")处理
为什么 send() 发出去的字符串客户端收不到?
典型表现:服务端 log 显示已 send,但 telnet 或 nc 看不到回显。多数情况是协议不匹配或缓冲未刷新。
- 确认客户端是否期待换行符——
text协议下,$connection->send('hello')不会自动加\n,得写成$connection->send("hello\n") - 某些客户端(如 Python 的
socket.makefile())默认行缓冲,没遇到\n就不吐数据 - 避免发送二进制或含
\0的字符串,text协议底层用explode("\n", $data)分割,遇到\0会截断
并发量上不去,CPU 高但连接数卡在几百?
Workerman 默认单进程单线程模型,text 协议本身轻量,瓶颈往往出在阻塞操作或配置失当。
- 检查是否在
onMessage里用了同步 MySQL 查询、file_get_contents或sleep()—— 这些会让整个进程卡住,所有连接排队 -
Worker::$count设太高(比如 > CPU 核数×2)反而增加上下文切换开销,建议从4起步压测 - 确保启动时用了
-d参数(如php start.php start -d),否则信号处理异常会导致子进程无法回收
text 协议只是最简分隔约定,别把它当成 HTTP 那样的完整协议栈。










