Как отправлять сообщения конкретным пользователям Ratchet PHP Websocket

7

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

Код PHP

Chat.php

<?php
namespace MyApp;
use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;

class Chat implements MessageComponentInterface
{
    protected $clients;

    public function __construct()
    {
        $this->clients = new \SplObjectStorage;
    }

    public function onOpen(ConnectionInterface $conn)
    {
        $this->clients->attach($conn);
    }

    public function onMessage(ConnectionInterface $conn, $msg)
    {
        foreach ($this->clients as $client)
        {
            if($conn !== $client)
                $client->send($msg);
        }
    }

    public function onClose(ConnectionInterface $conn)
    {
        $this->clients->detach($conn);
    }

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

server.php

<?php
use Ratchet\Server\IoServer;
use Ratchet\Http\HttpServer;
use Ratchet\WebSocket\WsServer;
use MyApp\Chat;

require dirname(__DIR__) . '/Ratchet/vendor/autoload.php';

$server = IoServer::factory(
  new HttpServer(
    new WsServer(
      new Chat()
    )
  ),
  8080
);

$server->run();
?>

Клиентский код js

<script type="text/javascript">
var conn = new WebSocket('ws://localhost:8080');

conn.onopen = function(e) {
  console.log("Connection established!");
};

conn.onmessage = function(e) {
  console.log(e.data);
};
</script>
Теги:
websocket
real-time
ratchet

2 ответа

23
Лучший ответ

В принципе, вам нужен синтаксис для отправки данных в WebSocket, я рекомендую использовать объект JSON для этого. В вашем классе WebSocket вам понадобится локальная переменная с именем subscriptions и локальная переменная с именем users.

<?php
namespace MyApp;
use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;

class Chat implements MessageComponentInterface
{
    protected $clients;
    private $subscriptions;
    private $users;

    public function __construct()
    {
        $this->clients = new \SplObjectStorage;
        $this->subscriptions = [];
        $this->users = [];
    }

    public function onOpen(ConnectionInterface $conn)
    {
        $this->clients->attach($conn);
        $this->users[$conn->resourceId] = $conn;
    }

    public function onMessage(ConnectionInterface $conn, $msg)
    {
        $data = json_decode($msg);
        switch ($data->command) {
            case "subscribe":
                $this->subscriptions[$conn->resourceId] = $data->channel;
                break;
            case "message":
                if (isset($this->subscriptions[$conn->resourceId])) {
                    $target = $this->subscriptions[$conn->resourceId];
                    foreach ($this->subscriptions as $id=>$channel) {
                        if ($channel == $target && $id != $conn->resourceId) {
                            $this->users[$id]->send($data->message);
                        }
                    }
                }
        }
    }

    public function onClose(ConnectionInterface $conn)
    {
        $this->clients->detach($conn);
        unset($this->users[$conn->resourceId]);
        unset($this->subscriptions[$conn->resourceId]);
    }

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

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

<script type="text/javascript">
var conn = new WebSocket('ws://localhost:8080');

conn.onopen = function(e) {
  console.log("Connection established!");
};

conn.onmessage = function(e) {
  console.log(e.data);
};

function subscribe(channel) {
    conn.send(JSON.stringify({command: "subscribe", channel: channel}));
}

function sendMessage(msg) {
    conn.send(JSON.stringify({command: "message", message: msg}));
}
</script>

Примечание. Этот код непроверен. Я написал его "на лету" из моего опыта с Ratchet. Удачи:)

  • 0
    На самом деле мне нужно использовать Ratchet Pusher. И я сделал, что все работает нормально, но теперь проблема в том, что клиент отключается после нескольких минут простоя без какого-либо сообщения об отключении, он перестает получать сообщение. Если я продолжаю посылать сообщения клиенту каждые 10 минут, он не отключается, но если есть промежуток, например, более 20 минут или около того, клиент не получает сообщение.
  • 0
    @RohitKhatri что вы используете для подключения к веб-сокету? Вы используете его через nginx или что-то еще?
Показать ещё 1 комментарий
0
// SOCKET VARIABLE DECLARATION
var mySocket;

// MESSAGE
const socketMessageListener = function(event) {
    var data = JSON.parse(event.data);
};

// OPEN SOCKET
const socketOpenListener = function(event) {
    console.log('Connected');
};

// CLOSE OR DISCONNECT SOCKET
const socketCloseListener = function(event) {
    if (mySocket) {
        console.error('Disconnected.');
    }
    mySocket = new WebSocket('ws://localhost:8080');
    mySocket.addEventListener('open', socketOpenListener);
    mySocket.addEventListener('message', socketMessageListener);
    mySocket.addEventListener('close', socketCloseListener);
};

// CALL THE LISTENER
socketCloseListener();

function sendMessage(data) {
    mySocket.send(JSON.stringify(data));
}

user3049006 Я нашел этот код в своем исследовании, чтобы сохранить соединение постоянным, если не удается, повторите попытку соединения снова.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню