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

Ratchet Pawl循环中无法向WebSocket发送消息问题排查求助

问题分析与解决方案

你的代码里send()始终不执行的核心原因,是在React EventLoop的回调中使用了阻塞性操作,彻底卡死了事件循环,导致WebSocket的异步Promise回调永远没机会运行。

为什么会这样?

ReactPHP的事件循环是单线程驱动的,所有异步逻辑(比如WebSocket连接、定时器、IO事件)都依赖循环能持续迭代、处理队列中的任务。但你在addPeriodicTimer的回调里写了:

  • sleep(1):这是同步阻塞函数,会直接让整个线程暂停1秒,期间事件循环完全停止工作。
  • 外层的do-while循环:会一直轮询串口直到数据长度达标,这个过程也是同步阻塞的,事件循环根本没时间去处理WebSocket连接的后续回调。

哪怕你看到了INVIO的输出,后面的connector()->then(...)里的逻辑也因为事件循环被阻塞,永远得不到执行的机会。

修复方案:移除阻塞操作,用异步方式重构逻辑

我们需要把同步阻塞的串口轮询,改成基于EventLoop的异步逻辑,绝对不能让任何回调卡住事件循环。

修改后的代码示例

$loop = \React\EventLoop\Factory::create();
$reactConnector = new \React\Socket\Connector($loop, ['dns' => '8.8.8.8', 'timeout' => 10]);
$connector = new \Ratchet\Client\Connector($loop, $reactConnector);

// 定义递归的异步串口读取函数
$readSerialAsync = function () use ($loop, $connector) {
    $msg = $this->getSerial()->read();
    echo "LETTO <$msg>\n";

    // 如果数据长度不够,1秒后通过EventLoop定时器再次读取
    if (strlen($msg) < 50) {
        $loop->addTimer(1, $readSerialAsync);
        return;
    }

    echo "INVIO $msg\n";
    // 此时事件循环是空闲的,可以正常处理WebSocket的异步逻辑
    $connector('ws://127.0.0.1:9988')
        ->then(function(Ratchet\Client\WebSocket $conn) use ($msg) {
            $conn->on('close', function($code = null, $reason = null) {
                echo "Connection closed ({$code} - {$reason})\n";
            });
            $conn->send($msg);
            $conn->close();
        }, function(\Exception $e) {
            echo "Could not connect: {$e->getMessage()}\n";
        });
};

// 每8秒启动一次串口读取流程
$loop->addPeriodicTimer(8, function () use ($readSerialAsync) {
    echo "LOOP\n";
    $readSerialAsync();
});

$loop->run();

关键优化点说明

  1. 替换sleep为EventLoop定时器:用$loop->addTimer(1, $readSerialAsync)代替sleep(1),这样等待过程中事件循环可以继续处理其他任务,不会阻塞。
  2. 递归轮询而非同步循环:把do-while改成递归调用,每次读取后如果数据不达标,就通过定时器安排下一次读取,让事件循环有喘息的机会。
  3. 优先使用异步串口库:如果你的串口库支持异步读取(比如ReactPHP官方的react/serialport扩展),更推荐直接监听串口的data事件,完全不需要轮询,效率会更高。

重要提醒

在ReactPHP的事件循环中,绝对禁止使用任何同步阻塞的函数或长时间运行的同步逻辑,比如sleep、usleep、同步IO读取、复杂的同步计算等,这些都会直接导致事件循环停滞,所有异步回调都无法执行。

内容的提问来源于stack exchange,提问作者Maxxer

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 04:30:12