PHP不能直接作为WebSocket客户端发起长连接,因其默认不支持原生WebSocket客户端,需借助ext-websocket扩展或reactphp/websocket等异步库实现。

PHP 不能直接作为 WebSocket 客户端发起长连接
PHP 默认不支持原生 WebSocket 客户端(比如像 JavaScript 的 new WebSocket() 那样维持持久双工通信)。它的 fsockopen() 或 stream_socket_client() 可以发 HTTP 握手请求,但无法自动处理帧解析、心跳、掩码、分片等 WebSocket 协议细节。强行手写完整协议实现极易出错,也不推荐。
用 ext-websocket 或 reactphp/websocket 是更现实的选择
生产环境建议使用成熟扩展或异步库:
-
ext-websocket(PECL 扩展):需编译安装,提供websocket_connect()、websocket_send()等函数,底层封装了协议逻辑,适合轻量客户端场景 -
reactphp/websocket(Composer 包):基于 ReactPHP 异步事件循环,支持完整 WebSocket 客户端/服务端,适合需要并发连接或与现有异步流程集成的项目 - 避免用
cURL或普通file_get_contents()—— 它们只支持 HTTP 请求,无法维持升级后的 WebSocket 连接
最简可行示例:用 reactphp/websocket 发起连接
先安装:
composer require react/http react/websocket然后运行以下脚本(注意它必须在命令行下执行,不能通过 Web 服务器运行):
require 'vendor/autoload.php';
use React\WebSocket\Client;
$loop = \React\EventLoop\Factory::create();
$client = new Client($loop);
$client->connect('ws://echo.websocket.org')->then(function ($connection) {
$connection->send('hello');
$connection->on('message', function ($msg) {
echo "收到: " . $msg->getPayload() . "\n";
});
}, function ($error) {
echo "连接失败: " . $error->getMessage() . "\n";
});
$loop->run();
关键点:
立即学习“PHP免费学习笔记(深入)”;
- 必须用
$loop->run()启动事件循环,否则连接会立即退出 -
ws://地址不能是http://,也不能是本地未运行服务的地址(如ws://localhost:8080要确保后端 WebSocket 服务已启动) - 错误回调里检查
$error->getMessage(),常见报错如Connection refused或Handshake failed,说明服务不可达或协议不匹配
如果只是想「发一次消息就断开」,用 curl + WebSocket 服务代理更实际
很多所谓“PHP 连 WebSocket”的需求,本质只是向 WebSocket 服务推送一条指令(例如通知前端刷新)。这种场景不该让 PHP 自己连 WS,而应:
- 让 WebSocket 服务额外暴露一个 HTTP 接口(如
POST /api/push),由 PHP 用curl_init()调用 - 该接口内部将消息转发给在线的 WebSocket 连接(例如通过 Redis Pub/Sub 或进程间通信)
- 避免 PHP 进程长期阻塞、超时、内存泄漏等问题
真正需要 PHP 持有 WebSocket 连接的场景极少,多见于后台监控客户端、IoT 设备桥接器等特殊用途——这时务必确认 PHP 运行模式(CLI)、事件循环兼容性、以及连接保活策略。











