Я пытаюсь создать систему, в которой пользователь может подписаться на категорию при установлении соединения с сервером 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, я рекомендую использовать объект 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. Удачи:)
// 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 Я нашел этот код в своем исследовании, чтобы сохранить соединение постоянным, если не удается, повторите попытку соединения снова.