客户端消息onmessage收不到,根本原因是监听地址为127.0.0.1导致外部请求被内核丢弃,必须改为0.0.0.0:端口并完整重启;同时需确保协议一致(tcp/http/websocket)、防火墙/安全组放行端口,并用ss -tuln和file_put_contents日志验证生效。

Workerman服务端明明运行着,客户端也显示已连接,但发来的消息在onMessage里完全收不到,日志里连连接建立的痕迹都没有——这种情况不是代码漏写了回调,而是网络层或协议层根本没把数据送到Workerman手里。
检查监听地址是否对外暴露
打开你的启动文件(如start.php),找到Worker实例化那行,确认协议地址写的是0.0.0.0:端口号,而不是127.0.0.1:端口号。
这一步必须改:监听127.0.0.1只响应本机回环请求,外部设备(哪怕同局域网)发包过来,Linux内核直接丢弃,Workerman连SYN都收不到,更别说onMessage了。
改完不能只reload:执行php start.php stop && php start.php start完整重启,否则旧配置仍在内存中生效。
验证是否生效:运行ss -tuln | grep :你的端口,看到*:你的端口或0.0.0.0:你的端口才算成功;如果还显示127.0.0.1:你的端口,说明代码没重载或被其他配置覆盖。
确认客户端实际走的是TCP还是HTTP协议
方法一:用curl测试HTTP请求(适合启用了Http协议的Worker)
执行curl -X POST -d "msg=test" http://服务器IP:端口/,再看onMessage是否触发。如果没反应,大概率你启的是TCP Worker,却用HTTP方式发包——TCP Worker根本不解析HTTP头,收到的只是原始字节流,可能因缺少换行或协议头被直接忽略。
方法二:用telnet或netcat直连TCP端口(适合裸TCP Worker)
执行telnet 服务器IP 端口,连上后手动敲一行文字+回车。如果onMessage立刻打印出内容,说明TCP通路正常;如果无响应,问题不在Workerman逻辑层,而在网络或防火墙。
【关键前提】客户端和服务端协议类型必须严格一致:硬件模块(如ESP32)默认发裸TCP,你就不能用websocket://0.0.0.0:8080启动——握手失败会导致秒断,且onMessage根本不会被调用。
排查防火墙与云安全组拦截
第一步:在服务器本地执行telnet 127.0.0.1 端口,能通≠外部能通。loopback流量不经过firewalld或云安全组,这只是验证Workerman进程本身是否存活。
第二步:查当前开放端口sudo firewall-cmd --list-ports,若列表里没有你的端口,立即添加:sudo firewall-cmd --add-port=端口号/tcp --permanent,然后sudo firewall-cmd --reload。
第三步:如果是阿里云、腾讯云等,必须登录控制台进「安全组」,添加入方向规则,协议选TCP,端口填你的端口号,源IP先设为0.0.0.0/0用于测试——很多故障就卡在这一步,控制台规则没配,光改服务器防火墙没用。
Windows/macOS下跑WSL或VirtualBox时,宿主机系统防火墙也要关掉或加例外,否则流量在进虚拟网卡前就被拦了。
验证onMessage是否真被触发
在onMessage回调开头强行加一句日志:file_put_contents('/tmp/workerman.log', date('Y-m-d H:i:s') . " onMessage triggered\n", FILE_APPEND);。
然后让客户端发一次消息,立刻执行tail -f /tmp/workerman.log盯住输出。如果日志完全没新增,说明数据根本没进到Workerman事件循环;如果有时间戳但没打印$data内容,才是协议解析或编码问题。
注意:某些IDE调试器或PHP-FPM环境会屏蔽标准输出,echo/print_r可能看不见,但file_put_contents一定落盘,这是最可靠的触发验证手段。
检查连接是否被意外关闭
① 在onConnect回调里加日志,确认客户端连上来时Workerman有没有记录;
② 在onClose回调里加日志,看连接是主动断开还是被动踢出;
③ 如果onConnect有日志、onMessage始终没有,且onClose也没触发,基本可断定数据包在网络链路中丢失或被中间设备(如路由器、负载均衡)静默丢弃。
此时需用tcpdump抓包:tcpdump -i any port 端口号 -w debug.pcap,然后用Wireshark打开,过滤客户端IP,确认SYN→SYN-ACK→ACK三次握手是否完成,以及客户端发的DATA包服务端是否真的收到了。











