必须确保swoole扩展已安装且启用websocket与coroutine功能,通过php --ri swoole验证;使用composer require topthink/think-swoole:^4.0安装兼容版本;在config/swoole.php中正确配置websocket为数组结构并指定有效handler和route_file;wshandler类中onopen必须主动push数据完成握手;nginx反代需透传upgrade和connection头以返回101响应。

要在ThinkPHP 6.0中让WebSocket连接成功完成协议升级并进入稳定通信状态,必须确保客户端发起的HTTP升级请求能被Swoole正确识别、验证并返回101 Switching Protocols响应——任何一环缺失都会导致连接卡在pending或立即关闭。
确认底层环境支持WebSocket与协程
执行php --ri swoole命令,检查输出中是否同时存在websocket => enabled和coroutine => enabled。若仅显示前者,说明协程未启用,后续onMessage事件将无法并发处理消息,多个客户端发消息时会排队阻塞;若两者皆无,【必须先安装Swoole扩展并重启PHP服务】,否则所有配置和代码均无效。
运行composer require topthink/think-swoole:^4.0,注意版本号不能省略,v3.x不兼容TP6.0的事件处理器契约,强行使用会导致握手后无法触发onOpen逻辑。
配置swoole.php启用WebSocket模块
打开config/swoole.php,将'websocket'项设为数组结构:'websocket' => ['enabled' => true]。写成'websocket' => true会导致Swoole内部跳过WebSocket协议解析,客户端永远收不到101响应。
'handler' => \app\listener\WsHandler::class——类路径必须带完整命名空间,且该类文件必须真实存在;Swoole启动时不报错,但客户端一连接就静默断开,毫无日志提示。
'route_file' => app_path() . 'websocket.php'——这个路径需手动创建空文件,若不存在,服务启动时报“Route file not found”并直接退出。
实现WsHandler并完成握手核心逻辑
第一步:创建app/listener/WsHandler.php,继承think\swoole\websocket\WsHandler,重写onOpen方法。
第二步:在onOpen中调用$server->push($fd, json_encode(['code'=>0,'msg'=>'connected'])),这一步不是可选——Swoole要求握手成功后必须至少主动推送一次数据,否则部分浏览器(尤其是iOS Safari)会判定握手失败并关闭连接。
第三步:确保onMessage中对空消息或非法JSON做容错处理,例如json_decode($data, true) === null时直接return,避免因单条错误消息导致整个worker进程崩溃,进而使新连接无法完成握手。
第四步:在onClose中清理fd关联的用户状态,否则重复连接同一账号时,旧fd残留会导致广播消息发给已断开的客户端,表现为“别人发的消息自己收不到,但能看到自己发的”。
启动服务并验证101握手响应
执行php think swoole启动服务,观察控制台是否输出Swoole WebSocket server started及监听地址端口。
用浏览器开发者工具Network面板过滤ws或wss,发起连接时检查Headers → Response Headers中是否存在HTTP/1.1 101 Switching Protocols、Upgrade: websocket、Connection: Upgrade三项——缺一不可。
若看到502 Bad Gateway或ERR_CONNECTION_REFUSED,立即检查Nginx反向代理配置中是否包含proxy_set_header Upgrade $http_upgrade和proxy_set_header Connection "Upgrade",漏掉任一字段都会中断协议升级流程。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











