ReactPHP Socket Client连接超时问题:无法触发连接失败事件
ReactPHP Socket 连接失败触发与自动重试解决方案
你的核心问题是默认Connector没有设置连接超时,当目标WebSocket服务器离线时,连接请求会一直挂起,无法触发失败回调。结合你的需求,以下是可直接运行的修复方案:
关键修复点
- 必须使用
TimeoutConnector包装基础连接器,强制设置连接超时时间 - 确保事件循环正常运行(ReactPHP异步操作的核心依赖)
- 封装连接逻辑实现自动重试
完整代码示例
<?php require __DIR__ . '/vendor/autoload.php'; use React\EventLoop\Loop; use React\Socket\Connector; use React\Socket\TimeoutConnector; use React\Socket\ConnectionInterface; // 获取全局事件循环实例 $loop = Loop::get(); // 初始化基础Socket连接器 $baseConnector = new Connector($loop); // 包装为带超时限制的连接器,设置5秒超时 $timeoutConnector = new TimeoutConnector($baseConnector, 5.0, $loop); // 封装连接逻辑,用于重试调用 $attemptConnection = function () use ($timeoutConnector, &$attemptConnection, $loop) { echo "[".date('Y-m-d H:i:s')."] 尝试连接WebSocket服务器...\n"; $timeoutConnector->connect('localhost:1234') ->then( // 连接成功回调 function (ConnectionInterface $connection) use ($loop) { echo "[".date('Y-m-d H:i:s')."] 连接成功!\n"; // 监听服务器推送数据 $connection->on('data', function ($data) { echo "[".date('Y-m-d H:i:s')."] 收到数据: {$data}\n"; }); // 连接正常断开事件 $connection->on('end', function () { echo "[".date('Y-m-d H:i:s')."] 连接正常断开\n"; }); // 连接关闭后触发重试 $connection->on('close', function () use ($attemptConnection, $loop) { echo "[".date('Y-m-d H:i:s')."] 连接关闭,5秒后重试...\n"; $loop->addTimer(5.0, $attemptConnection); }); // 连接建立后的错误事件监听 $connection->on('error', function (\Exception $e) { echo "[".date('Y-m-d H:i:s')."] 连接出错: {$e->getMessage()}\n"; }); }, // 连接失败回调 function (\Exception $e) use ($attemptConnection, $loop) { echo "[".date('Y-m-d H:i:s')."] 连接失败: {$e->getMessage()},5秒后重试...\n"; $loop->addTimer(5.0, $attemptConnection); } ); }; // 首次触发连接 $attemptConnection(); // 启动事件循环(必须,否则异步操作无法执行) $loop->run();
核心逻辑说明
- 超时控制:
TimeoutConnector会在指定时间内(示例为5秒)判断连接是否成功,超时则直接触发失败回调 - 自动重试:将连接逻辑封装为可递归调用的函数,在失败或连接关闭后,通过
addTimer延迟指定时间重试 - 事件循环依赖:ReactPHP的所有异步操作(连接、定时器、事件监听)都必须在事件循环运行时才能生效,因此最后必须调用
$loop->run()
内容的提问来源于stack exchange,提问作者Bill Kervaski
相关产品推荐
相关产品推荐

