Ratchet WebSocket - 立即发送消息

8

我需要在发送信息的过程中进行一些复杂的计算,但是第一条信息必须在计算后立即发送,应该怎么做?

<?php

namespace AppBundle\WSServer;

use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;

class CommandManager implements MessageComponentInterface {

    public function onOpen(ConnectionInterface $conn) {
        //...
    }

    public function onClose(ConnectionInterface $connection) {
        //...
    }

    public function onMessage(ConnectionInterface $connection, $msg) {
        //...
        $connection->send('{"command":"someString","data":"data"}');

        //...complicated computing
        sleep(10);
   
        //send result
        $connection->send('{"command":"someString","data":"data"}');
        return;
    }
}

启动服务器:

$server = IoServer::factory(
              new HttpServer(
                  new WsServer(
                      $ws_manager
                  )
              ), $port
);

你可以使用每毫秒运行的EventLoop和自己的消息队列来发送消息。 - MarshallOfSound
这是一个不错的想法,但我认为它并不是最优解决方案(有很多迭代,却什么也没做)。不幸的是,我不知道更好的方法。 - Redkrytos
是的,这种建议有点像最后的手段。除非覆盖Ratchet的一些核心部分,否则很难实现。我想你可以使用Symfony来启动一个新的进程来处理计算任务。 - MarshallOfSound
1个回答

1

send最终会到达React的事件循环(EventLoop),当它准备好时异步发送消息。与此同时,它放弃执行权,然后脚本执行您的计算。在此期间,缓冲区将发送您的第一个和第二个消息。为了避免这种情况,您可以告诉计算在当前缓冲区排干后,在EventLoop上作为一个tick来执行:

class CommandMessage implements \Ratchet\MessageComponentInterface {
    private $loop;
    public function __construct(\React\EventLoop\LoopInterface $loop) {
        $this->loop = $loop;
    }

    public function onMessage(\Ratchet\ConnectionInterface $conn, $msg) {
        $conn->send('{"command":"someString","data":"data"}');

        $this->loop->nextTick(function() use ($conn) {
            sleep(10);

            $conn->send('{"command":"someString","data":"data"}');
        });
    }
}

$loop = \React\EventLoop\Factory::create();

$socket = new \React\Socket\Server($loop);
$socket->listen($port, '0.0.0.0');

$server = new \Ratchet\IoServer(
    new HttpServer(
        new WsServer(
            new CommandManager($loop)
        )
    ),
    $socket,
    $loop
);

$server->run();

此答案已不准确,您是否介意更新?似乎他们将nextTick重命名为futureTick,但即使如此,它现在仍然没有影响。 - InterLinked

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接