PHP本身不原生支持WebSocket客户端或服务端,因其短生命周期、同步阻塞模型与WebSocket所需的常驻进程、异步I/O及帧协议处理存在根本冲突;cURL和file_get_contents均无法维持连接或解析WebSocket帧,故不可用;推荐客户端用textalk/websocket库,服务端生产环境优选Swoole或Workerman,二者均需CLI常驻运行并配置心跳与安全校验。

PHP 本身不支持 WebSocket 客户端或服务端原生运行,这不是语法问题,而是运行模型冲突:PHP 默认以短生命周期、同步阻塞方式处理 HTTP 请求,而 WebSocket 要求常驻进程、异步 I/O 和帧协议处理。直接硬写 socket_create 或用 fsockopen 连 ws:// 地址,99% 会卡在握手或收不到消息。
为什么 cURL 和 file_get_contents 都连不上 WebSocket
它们只走完 HTTP 握手就断开,根本不会进入 WebSocket 帧通信阶段:
-
cURL访问ws://会报错:Protocol "ws" not supported or disabled in libcurl - 即使伪造
Upgrade: websocket头,cURL 也不会维持连接、不解析掩码(masking)、不处理0x81帧头 -
file_get_contents是纯请求-响应模型,连握手都发不出去——它不支持设置自定义 header 后保持 socket
PHP WebSocket 客户端该用哪个库
真要从 PHP 发起连接(比如调试、IoT 设备上报、后台任务通知),textalk/websocket 是目前最轻量靠谱的选择:
- 依赖
reactphp/socket管理底层 TCP,自己实现握手和帧编解码,不依赖扩展 - 安装简单:
composer require textalk/websocket - 基本用法干净:
$client = new \WebSocket\Client("ws://echo.websocket.org"); $client->send("hello"); echo $client->receive(); - 注意:
ws://URL 不能带 query 参数(如?token=xxx),部分版本会解析失败;参数应放headers里 - 超时默认 5 秒,可传配置:
new \WebSocket\Client($url, ["timeout" => 10])
PHP WebSocket 服务端该选 Swoole 还是 Workerman
别碰 Ratchet —— 它基于 ReactPHP,事件循环在 PHP 层,高并发下 CPU 占用高、内存泄漏风险大,2024 年后已基本无人维护。生产环境只看两个:
立即学习“PHP免费学习笔记(深入)”;
- Swoole:需编译安装扩展,性能强、协程友好,适合中大型项目;但对 Docker 多线程环境、某些云函数平台兼容性差
-
Workerman:纯 PHP 实现,
composer require workerman/workerman即装即用,部署零门槛;单机万级连接无压力,适合快速验证和中小业务 - 两者都不支持 Apache / PHP-FPM 模式运行——必须用 CLI 启动常驻进程,且端口需防火墙放行
- 务必加心跳:客户端不发 ping,服务端默认 60 秒断连;Workerman 可设
$ws->pingInterval = 25;,Swoole 用onMessage拦截0x9ping 帧
真正容易被忽略的点是:WebSocket 不是“连上就能用”。服务端必须处理连接生命周期(如用户登录态绑定)、消息广播范围(全站?房间?私聊?)、断线重连策略(前端重连间隔指数退避)、以及——所有数据都要校验来源,因为 ws:// 连接没有 Cookie 自动携带,token 必须走 URL 参数或 Upgrade header,否则极易被未授权接入。



















