Может ли сервер Ratchet WebSocket отправлять сообщение самому клиенту?

Я хочу использовать храповик (http://socketo.me) для постоянного соединения между приложениями iPhone и сервером. И мне нужно обмениваться данными между приложениями и сервером.

из этого примера (http://socketo.me/docs/hello-world) я узнал, что у меня есть функция onMessage это будет вызвано, когда приложение отправит массаж на сервер, и сервер может отправить ответ на приложение.

но сервер также должен иметь возможность отправки данных в приложение без получения данных из приложения. Например, связь между приложением и сервером. Что-то произошло на сервере, и нам нужно отправить новые данные в приложение. Как я могу это сделать и возможно ли это?

главный вопрос: как я могу отправить данные от сервера?

Спасибо за любую помощь.

3 ответов


Это действительно возможно. Вам нужно как-то связаться с процессом сервера WebSocket. Вы можете сделать это, используя некоторую форму передачи сообщений, будь то RPC или очередь сообщений.

храповик сам основан на цикле событий React. Это означает, что любая форма связи с храповиком должна быть интегрирована с этим циклом событий. на главной странице React вы можете увидеть некоторые из интеграций, которые уже exist:

  • Predis / Async (вы можете использовать redis pub / sub для передачи сообщений)
  • DNode-PHP (dnode-это протокол RPC на основе TCP)
  • React/ZMQ (интегрирует цикл событий с ZeroMQ)
  • Реагировать/Топать (реализация протокола STOMP, позволяющая разговаривать с такими сообщениями, как RabbitMQ)
  • JCook21 / ReactAMQP (привязки AMQP для React PHP)

в документации храповика есть учебник о том, как использовать React/ZMQ для того, чтобы толкать сообщения из любого места на ваш сервер WebSocket.


храповик также реализует WAMP, который включает PubSub. Таким образом, ваши клиенты могут подписаться на некоторые темы, а другие клиенты (работающие на вашей инфраструктуре бэкэнда) могут публиковаться в этих темах. У вас может быть публикация клиента на основе AutobahnPython через храповик в мобильном приложении на основе AutobahnAndroid или клиенте HTML5 на основе AutobahnJS.


У меня был точно такой же вопрос и вот что я сделал.

на основе Привет мир учебник, Я заменил SplObjectStorage с массивом. Прежде чем представить мои изменения, я хотел бы прокомментировать, что если вы следовали через этот учебник и поняли его, единственное, что помешало вам прийти к этому решению самостоятельно, вероятно, не зная, что SplObjectStorage есть.

class Chat implements MessageComponentInterface {
    protected $clients;

    public function __construct() {
        $this->clients = array();
    }

    public function onOpen(ConnectionInterface $conn) {
        // Store the new connection to send messages to later
        $this->clients[$conn->resourceId] = $conn;
        echo "New connection! ({$conn->resourceId})\n";
    }

    public function onMessage(ConnectionInterface $from, $msg) {
        $numRecv = count($this->clients) - 1;
        echo sprintf('Connection %d sending message "%s" to %d other connection%s' . "\n"
            , $from->resourceId, $msg, $numRecv, $numRecv == 1 ? '' : 's');

        foreach ($this->clients as $key => $client) {
            if ($from !== $client) {
                // The sender is not the receiver, send to each client connected
                $client->send($msg);
            }
        }
        // Send a message to a known resourceId (in this example the sender)
        $client = $this->clients[$from->resourceId];
        $client->send("Message successfully sent to $numRecv users.");
    }

    public function onClose(ConnectionInterface $conn) {
        // The connection is closed, remove it, as we can no longer send it messages
        unset($this->clients[$conn->resourceId]);

        echo "Connection {$conn->resourceId} has disconnected\n";
    }

    public function onError(ConnectionInterface $conn, \Exception $e) {
        echo "An error has occurred: {$e->getMessage()}\n";

        $conn->close();
    }
}

конечно, чтобы сделать его действительно полезно вы также можете добавить соединение с БД и сохранить/получить эти resourceIds.