Workerman WebSocket连接失败90%因监听地址非0.0.0.0、代理未透传Upgrade头或网络链路异常;须先用ss -tuln确认*:端口监听,再查ps是否有worker进程、Nginx配置及协议一致性。

Workerman WebSocket 连接失败,90% 的情况不是代码写错了,而是监听地址、代理配置或网络链路没对上——先确认 ss -tuln | grep :端口 有 *:端口 输出,再往下查。
Workerman 真的在监听 0.0.0.0 吗?
很多人改了 $worker->listen('websocket://127.0.0.1:2345') 就以为完事了,结果客户端一连就 Connection refused。127.0.0.1 只响应本机回环,外部根本连不进来。
- 必须改成
websocket://0.0.0.0:2345或websocket://*:2345 - 改完重启服务,然后立刻执行
ss -tuln | grep :2345,看到*:2345才算生效;如果只看到127.0.0.1:2345,说明没生效或被覆盖 - ThinkPHP + Workerman 组合里,常在控制器属性如
$socket = 'websocket://127.0.0.1:2222'写死,得手动改掉 - Docker 容器内运行时,除了宿主机
-p 2345:2345,容器内监听也必须是0.0.0.0,否则映射无效
Nginx 反向代理漏传 Upgrade 头了?
前端用 wss:// 访问,但 Nginx 没透传关键头,浏览器发了握手请求,后端根本收不到,自然不会返回 101 Switching Protocols。
WebSocket 8.18.2 是该协议规范的一个重要迭代版本,主要优化了连接稳定性与数据传输效率。它通过全双工通信机制,允许客户端与服务器在单一长连接上实时交换数据,大幅降低传统 HTTP 轮询的开销。该版本增强了心跳保活、自动重连及二进制帧传输能力,适用于即时通讯、在线游戏及金融行情推送等低延迟场景,为开发者提供更可靠的实时网络交互基础。
- 检查对应
location块是否包含这三行(顺序无关,但缺一不可):proxy_http_version 1.1、proxy_set_header Upgrade $http_upgrade、proxy_set_header Connection "upgrade" -
$http_upgrade是 Nginx 内置变量,不能写成$upgrade或硬编码"websocket" - 改完必须执行
nginx -t && nginx -s reload,否则配置不生效 - Cloudflare / WAF 层也会吃掉
Upgrade头,若用了多层代理,每一层都要检查
客户端连的是 ws 还是 wss?协议和页面必须一致
HTTPS 页面里写 new WebSocket('ws://...'),浏览器直接拦截,Network 面板里连 WS 请求记录都不会出现,Console 里会报 Mixed Content。
- HTTP 页面 → 用
ws://;HTTPS 页面 → 必须用wss:// -
wss://要求服务端有有效 TLS 证书,自签名证书会被浏览器拒绝,连握手请求都发不出去 - URL 路径别多写斜杠,比如后端监听
/ws,客户端却连wss://host/ws/(末尾多 /),某些框架会 404 - 用真实客户端 IP 测试:在手机或另一台机器上执行
telnet your-server-ip 2345,别只信服务器本机telnet 127.0.0.1 2345
Workerman 进程到底跑起来了没有?
php start.php start 显示 Start success 不代表服务可用,master 进程起来,worker 进程可能因异常直接退出,日志里也不一定报错。
- 执行
ps aux | grep WorkerMan,至少要看到WorkerMan: worker process;只有master process,说明 worker 启动失败 - 查
workerman.log最末尾,找Fatal error、Exception或onWorkerStart抛出的异常 - 常见坑:PHP 版本太低(如 PHP 5.6)、扩展缺失(pcntl、posix)、文件权限不足、
onConnect回调里写了阻塞操作导致超时 - 启动时加
-d参数调试:php start.php start -d,看控制台实时输出
最易忽略的一点:Workerman 日志安静,ss 看不到监听,ps 没 worker 进程——这时候别急着改 Nginx 或前端,先盯住 workerman.log 末尾三行和 ps 输出,90% 的“连接失败”其实卡在进程根本没起来这一步。

















