You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ReactPHP Socket Client连接超时问题:无法触发连接失败事件

ReactPHP Socket 连接失败触发与自动重试解决方案

你的核心问题是默认Connector没有设置连接超时,当目标WebSocket服务器离线时,连接请求会一直挂起,无法触发失败回调。结合你的需求,以下是可直接运行的修复方案:

关键修复点

  1. 必须使用TimeoutConnector包装基础连接器,强制设置连接超时时间
  2. 确保事件循环正常运行(ReactPHP异步操作的核心依赖)
  3. 封装连接逻辑实现自动重试

完整代码示例

<?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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 10:37:04