核心问题是服务监听地址错误、nginx未透传upgrade头、客户端协议与服务端不匹配;需将$socket设为websocket://0.0.0.0:2222,nginx配置proxy_http_version 1.1及两个upgrade头,前端用wss://二级域名且由nginx终止ssl。

ThinkPHP配置二级域名后WebSocket连接失败,核心问题不在域名本身,而在于服务监听、反向代理和协议协商三个环节的配合失效。二级域名只是表象,真正卡住连接的是HTTP升级握手阶段的链路断裂。
监听地址必须用IP,不能依赖域名解析
Workerman是底层TCP服务,不走DNS解析。即使你在Nginx里配置了 ws.example.com → 127.0.0.1:2222,Workerman的$socket属性仍需明确绑定到可被外部访问的地址:
- 错误写法:
websocket://ws.example.com:2222(Workerman无法解析该域名) - 正确写法:
websocket://0.0.0.0:2222或websocket://服务器公网IP:2222 - 修改位置:ThinkPHP中Worker控制器(如
app\push\controller\WorkerController.php)里的$socket属性 - 改完务必重启服务:
php server.php restart,不是reload
Nginx必须透传Upgrade头,否则握手直接400
二级域名通常意味着前端有Nginx反代。若缺少关键Header,浏览器发来的Upgrade: websocket请求会被静默丢弃,返回400 Bad Request或直接超时:
- 在对应server块中加入三行(缺一不可):
proxy_http_version 1.1;proxy_set_header Upgrade $http_upgrade;proxy_set_header Connection "upgrade";- 确保location匹配的是WebSocket路径,例如:
location / { proxy_pass http://127.0.0.1:2222; ... } - 重载Nginx:
nginx -s reload,并用curl -i -N -H "Connection: Upgrade" -H "Upgrade: websocket" http://ws.example.com/手动测试升级是否响应101
客户端URL协议与子协议要和服务端严格一致
二级域名常伴随HTTPS部署,此时必须用wss://而非ws://;同时,若服务端未启用SSL,Nginx必须终止SSL并以明文转发到Workerman:
- 前端JS连接地址应为:
new WebSocket("wss://ws.example.com:443")(端口省略也可) - 若Nginx SSL终止成功,后端
proxy_pass仍指向http://127.0.0.1:2222,无需Workerman自己处理证书 - 避免使用子协议(如
['json-v1']),除非服务端显式支持并在响应头返回Sec-WebSocket-Protocol: json-v1 - 检查浏览器Network面板中WS请求的Response Headers,确认存在
Sec-WebSocket-Accept且无400/502等状态码
补充验证点:防火墙、端口映射与跨域
二级域名环境更容易忽略基础设施层问题:
- 云服务器安全组:放行的是
443(WSS)或80(WS)端口,不是Workerman监听的2222——因为流量不直连Workerman - 本地测试可用
telnet ws.example.com 443验证DNS+端口+SSL链路是否通 - Access-Control-Allow-Origin头由Nginx添加更稳妥(Workerman本身不处理CORS),例如:
add_header 'Access-Control-Allow-Origin' 'https://example.com'; - 宝塔用户请确认「网站」→「设置」→「反向代理」中已启用,并勾选「WebSocket支持」开关
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











