跳转到主内容
websoft网络软件专家 - 深耕网络技术,打造实用软件!

PHP怎样使用WebSocket_使用WebSocket实现实时通信【服务】

PHP不原生支持WebSocket服务端,需借助ReactPHP+Ratchet或Swoole等扩展;Ratchet依赖事件循环、需正确处理握手与消息生命周期;Swoole须用WebSocket\Server类并注意Nginx代理配置;连不上时应优先验证握手流程而非修改PHP逻辑。 PHP 本身不原生支持 WebSocket 服务端 PHP 没有内置的、开箱即用的 WebSocket 服务器能力,
fsockopen
或
stream_socket_server
只能做原始 TCP,无法直接处理 WebSocket 握手和帧解析。硬用 PHP 写完整 WebSocket 服务端容易出错,也不推荐。 实操建议: 用
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 错误或连接立即断开。 PHP 8.5.5 PHP 8.5.5 是 PHP 8.5 分支的维护更新版本。该版本延续了“小步快跑”的迭代逻辑,通过深度错误修复、底层性能微调以及安全加固,旨在为开发者提供一个更健壮、更高效的运行环境。该版本严格遵守语义化版本规范,不包含破坏性变更。 下载 使用场景:需要高并发(万级连接)、低延迟(如聊天室、协同编辑),且能控制部署环境(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 事情说清了就结束。WebSocket 的坑不在编码逻辑,而在协议细节、环境链路和错误信号的归属判断。连不上时,先问「握手有没有发出、有没有返回」,而不是急着改 PHP 代码。

相关文章