I need to send message to the client but not like response to it’s message.
In other words – i am doing some business logic on my server and when I got the result I want to send it to all clients. I tried with Redis, broadcasting, listening to particular redis channel. I am pretty confused at this point. My Socket.php
looks like this:
clients = new \SplObjectStorage;
}
public function onOpen(ConnectionInterface $conn)
{
// Store the new connection to send messages to later
$this->clients->attach($conn);
echo "New connection! ({$conn->resourceId})" . PHP_EOL;
}
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 $client) {
if ($from !== $client) {
//The sender is not the receiver, send to other clients
$client->send($msg);
}
}
}
public function onClose(ConnectionInterface $conn)
{
// The connection is closed, remove from connection list
$this->clients->detach($conn);
echo "Connection {$conn->resourceId} has disconnected" . PHP_EOL;
}
public function onError(ConnectionInterface $conn, \Exception $e)
{
echo "An error has occurred: {$e->getMessage()}" . PHP_EOL;
$conn->close();
}
public function broadcast($data)
{
echo "Broadcasting data to " . count($this->clients) . " clients" . PHP_EOL;
foreach($this->clients as $client) {
$client->send($data);
}
}
}
It is the basic example from ratchet. The only thing I added is the method broadcast
.
The server.php
:
'************,
'local_pk' => '************',
'allow_self_signed' => true, // Optional: only for self-signed certs
'verify_peer' => false // Optional: only for self-signed certs
]);
$newSocket = new Socket();
$broadcaster = new Broadcaster($newSocket);
if (pcntl_fork() === 0) {
$broadcaster->listen();
exit;
}
$ws = new WsServer($newSocket);
$httpServer = new HttpServer($ws);
// Create and run the server
$server = new IoServer($httpServer, $secureSocket, $loop);
// Redis subscriber loop
// $loop->addTimer(0.001, function () use ($newSocket) {
// echo 'test subscriber loop' . PHP_EOL;
// $redis = new Predis\Client([
// 'scheme' => 'tcp',
// 'host' => '127.0.0.1',
// 'port' => 12284
// ]);
// $pubsub = $redis->pubSubLoop();
// $pubsub->subscribe('broadcast');
// echo 'Pubsub instance: ' . json_encode($pubsub) . PHP_EOL;
// foreach ($pubsub as $message) {
// if ($message->kind === 'message') {
// echo "[Redis] Received: {$message->payload}\n";
// $newSocket->broadcast($message->payload);
// }
// }
// });
echo "🔒 WSS server running on wss://your-domain.com:8889\n";
$loop->run();
So here I am basically trying with pcntl_fork
and if process is on – I am trying to listen to the Redis channel. It doesn’t work. The commented part $loop->addTimer
is the other approach I tried. No success.
My Broadcast.php
:
server = $server;
$this->redis = new Redis([
'scheme' => 'tcp',
'host' => '127.0.0.1',
'port' => 12284
]);
}
public function listen(string $channel="broadcast")
{
$pubsub = $this->redis->pubSubLoop();
$pubsub->subscribe($channel);
echo "Listening to Redis channel: {$channel}" . PHP_EOL;
foreach ($pubsub as $message) {
if ($message->kind === 'message') {
echo "Recieved message: {$message->payload}" . PHP_EOL;
$this->server->broadcast($message->payload);
}
}
}
}
And finally my send.php
:
'tcp',
'host' => '127.0.0.1',
'port' => 12284
]);
echo $redis->publish('broadcast', 'My test server message') . " testing redis publisher" . PHP_EOL;
echo 'Message sent' . PHP_EOL;
I run the server, can connect client to it but when broadcast
method is called it return Broadcasting data to 0 clients
. This the echo
in the broadcast
method. So I can assume that I am not referring the clients from the current socket server somehow? Maybe?
Because I can’t really run second instance because the 8889 port is already taken. Hope I explained it correct.