Laravel中使用cboden/ratchet WebSocket包连接失败:未收到握手响应连接即关闭问题求助
我之前也碰到过这个一模一样的问题,折腾了好一阵才找到几个有效的排查方向,给你一步步来:
1. 先排查最可能的低级错误:命令拼写问题
看你的TestCommand里的命令签名是protected $signature = 'ratched:serve';——注意这里拼写是ratched(多了个d),而官方包名是Ratchet。如果你运行命令时输入的是php artisan ratchet:serve(正确拼写),那Laravel会找不到这个命令,服务器根本没启动!
赶紧确认:
- 要么把命令签名改成
'ratchet:serve'(去掉多余的d),要么运行命令时严格输入php artisan ratched:serve。
2. 验证Ratchet服务器是否真的在监听端口
服务器启动后,用以下命令检查8090端口是否被PHP进程占用:
# Linux/macOS lsof -i :8090 # 或者 netstat -anp | grep 8090 # Windows netstat -ano | findstr :8090
如果没有任何输出,说明服务器没有成功启动,可能是:
- PHP缺少
sockets扩展(Ratchet必须依赖这个扩展) - 命令执行时没有权限(虽然8090是高于1024的端口,一般不需要root,但还是要确认)
检查sockets扩展是否启用:
php -m | grep sockets
如果没有结果,需要安装扩展:
# Ubuntu/Debian sudo apt install php-sockets # CentOS/RHEL sudo yum install php-sockets # 安装后确保扩展生效,CLI模式一般无需重启PHP
3. 排查网络连接问题
如果服务器确实在监听端口,但客户端还是连不上:
本地测试:用
telnet localhost 8090测试连接,如果提示Connection refused,说明端口没开放;如果能连接,手动发送握手请求:GET / HTTP/1.1 Host: localhost:8090 Upgrade: websocket Connection: Upgrade Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ== Sec-WebSocket-Version: 13按两次回车,如果收到包含
Sec-WebSocket-Accept的响应,说明服务器握手逻辑没问题,问题在客户端代码或浏览器环境。跨环境测试:如果你是在Docker/虚拟机里运行Laravel,浏览器用
localhost会指向本机,而不是容器/虚拟机的IP,需要把客户端的WebSocket地址改成容器/虚拟机的实际IP,比如ws://192.168.1.100:8090/。防火墙/安全组:检查服务器的防火墙(比如
ufw、iptables)或者云服务器的安全组,是否允许8090端口的入站流量。
4. 检查你的ChatSocket实现
你的ChatSocket代码看起来是正确实现了MessageComponentInterface的四个方法,但还是要确认:
- 命名空间是否正确:
namespace App\Classes\Socket;,确保TestCommand里的use App\Classes\Socket\ChatSocket as Socket;能正确找到这个类。 - 有没有语法错误:运行
php artisan ratched:serve时,终端如果有报错(比如语法错误、类找不到),会直接终止服务器启动,一定要看终端输出!
5. 客户端代码的小细节
你的客户端代码里,WebSocket连接的路径是/,这没问题,但如果浏览器有缓存或者之前的连接残留,可以强制刷新页面(Ctrl+F5),或者在控制台里手动创建WebSocket实例测试。
另外,有些浏览器在HTTPS页面里不允许连接WS(非加密)的地址,如果你的Laravel是用HTTPS访问的,客户端需要用wss://协议,这时候你需要给Ratchet配置SSL证书,或者用反向代理(比如Nginx)来处理SSL握手。
内容的提问来源于stack exchange,提问作者desh

