php不原生支持websocket服务端,需借助reactphp+ratchet或swoole等扩展;ratchet依赖事件循环、需正确处理握手与消息生命周期;swoole须用websocket\server类并注意nginx代理配置;连不上时应优先验证握手流程而非修改php逻辑。

PHP 本身不原生支持 WebSocket 服务端
PHP 没有内置的、开箱即用的 WebSocket 服务器能力,fsockopen 或 stream_socket_server 只能做原始 TCP,无法直接处理 WebSocket 握手和帧解析。硬用 PHP 写完整 WebSocket 服务端容易出错,也不推荐。
实操建议:
一套自选网上商城精美模版,自主商品管理,自行网店经营的网上商城平台,系统具有强大的商品管理、购物车、订单统计、会员管理等功能,同时拥有灵活多变的商品管理、新闻管理等功能,功能强劲的后台管理界面,无需登录FTP,通过IE浏览器即可管理整个网站。西亚购物平台经多方面权威调查和研究为您精心开发了很多特色实用功能。使商品展示、管理、服务全面升级。西亚购物平台为您提供了多款专业美观的店面样式、俱备完整的购物
- 用
ReactPHP+Ratchet(稳定、事件驱动,适合中小规模实时推送) - 用
Swoole(性能高,支持WebSocket\Server类,但需编译扩展,PHP 8.0+ 兼容性更好) - 别用
Workerman的旧版Websocket类直接裸写协议——它已弃用,新版统一走Worker+WebsocketConnection - 如果只是临时调试,可用
npm install -g wscat连接本地服务端验证,避免浏览器 CORS 干扰
Ratchet 实现 WebSocket 服务端的关键三步
Ratchet 是最贴近“纯 PHP”思维的方案,但必须理解它的生命周期:连接 → 收消息 → 关闭,不维护全局状态,所有上下文靠 $conn 对象传递。
常见错误现象:Connection closed before receiving a handshake response —— 通常是没调用 $conn->send() 前就 return,或握手阶段抛了未捕获异常。
立即学习“PHP免费学习笔记(深入)”;
实操建议:
- 入口文件必须用
react/http-server启动,不能用php -S(不支持长连接) -
onOpen()中不要做耗时操作(如查 DB),会阻塞整个 event loop -
onMessage()接收到的是原始字符串,JSON 需手动json_decode($msg, true),别假设是数组 - 广播给所有人?用
$this->clients->broadcast($msg),但注意$this->clients是ConnectionInterface集合,不是数组
Swoole 启动 WebSocket 服务时的路径陷阱
Swoole\Http\Server 和 Swoole\WebSocket\Server 是两套东西:前者只能代理 WebSocket 请求,后者才是真服务端。混淆会导致 400 错误或连接立即断开。
使用场景:需要高并发(万级连接)、低延迟(如聊天室、协同编辑),且能控制部署环境(Linux + Swoole 扩展)。
实操建议:
- 启动代码必须用
new Swoole\WebSocket\Server('0.0.0.0', 9501),别错写成Http\Server -
on('start')回调里不能 echo 输出,否则污染 WebSocket 协议头 -
$server->connections是连接 fd 列表,要发消息得用$server->push($fd, $data),不是send() - 若配合 Nginx,Nginx 配置里必须有
proxy_http_version 1.1和Upgrade $http_upgrade,否则握手失败
前端连不上?先确认 WebSocket 握手是否成功
浏览器控制台看到 WebSocket connection to 'ws://...' failed,90% 不是 PHP 问题,而是网络或协议层卡在握手。
性能 / 兼容性影响:HTTP/2 环境下某些代理会吞掉 Upgrade 头;自签名证书下 wss:// 在 Chrome 会直接拒绝,哪怕加了例外。
实操建议:
- 用
curl -i -N -H "Connection: Upgrade" -H "Upgrade: websocket" http://localhost:9501手动模拟握手,看返回是否有HTTP/1.1 101 Switching Protocols - 检查 PHP 服务监听地址:
0.0.0.0才能被外网访问,127.0.0.1仅限本机 - Chrome 开发者工具 Network 标签页中过滤
ws,点开连接看 Headers → Request Headers 是否含Sec-WebSocket-Key,Response Headers 是否含Sec-WebSocket-Accept - 别在
onOpen里直接var_dump($conn)—— 它不可序列化,会 crash 整个 worker










