Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ratchet WebSocket - send message immediately

I have to do some complicated computing between sending messages, but first message is sent with second after compulting. 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 compulting
        sleep(10);

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

Starting server:

$server = IoServer::factory(
              new HttpServer(
                  new WsServer(
                      $ws_manager
                  )
              ), $port
);
like image 935
Redkrytos Avatar asked Nov 10 '22 11:11

Redkrytos


1 Answers

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();
like image 165
cboden Avatar answered Nov 15 '22 06:11

cboden