Ratchet WebSocket - send message immediately

1.9k views Asked by At

I have to do some complicated computing between sending messages, but first message is sent with second after computing. How I can send it immediately?

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

Starting server:

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

There are 1 answers

1
cboden On

send eventually makes its way to React's EventLoop which sends the message asynchronously when it's "ready". In the mean time it relinquishes execution and then the scripts executes your calculation. By the time that's done the buffer will then send your first and second messages. To avoid this you can tell the calculation to execute on the EventLoop as a tick after the current buffers are drained:

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();