Como enviar dados para um cliente específico no Workerman
Ao utilizar o Worker como servidor, sem o GatewayWorker, como posso enviar mensagens para um usuário específico?
<?php
use Workerman\Worker;
use Workerman\Connection\TcpConnection;
require_once __DIR__ . '/vendor/autoload.php';
// Inicializa um container worker, escutando na porta 1234
$worker = new Worker('websocket://workerman.net:1234');
// ====O número de processos deve ser definido como 1====
$worker->count = 1;
// Adiciona um atributo para mapear o uid para a conexão (uid é o id do usuário ou o identificador único do cliente)
$worker->uidConnections = array();
// Função de callback quando um cliente envia uma mensagem
$worker->onMessage = function(TcpConnection $connection, $data)
{
global $worker;
// Verifica se o cliente atual já foi autenticado, isto é, se o uid foi definido
if(!isset($connection->uid))
{
// Se não estiver autenticado, o primeiro pacote é tratado como uid (Para fins de demonstração, não é feita uma verificação real)
$connection->uid = $data;
/* Mapeia o uid para a conexão, o que permite encontrar a conexão facilmente através do uid e enviar dados direcionados a um uid específico */
$worker->uidConnections[$connection->uid] = $connection;
return $connection->send('Login realizado com sucesso, seu uid é ' . $connection->uid);
}
// Outra lógica para enviar a um uid específico, ou para fazer uma transmissão global
// Assume-se que o formato da mensagem é uid:mensagem para enviar a mensagem para um uid específico
// Se o uid for "all", é feita uma transmissão global
list($recv_uid, $message) = explode(':', $data);
// Transmissão global
if($recv_uid == 'all')
{
broadcast($message);
}
// Envia para um uid específico
else
{
sendMessageByUid($recv_uid, $message);
}
};
// Quando um cliente se desconecta
$worker->onClose = function(TcpConnection $connection)
{
global $worker;
if(isset($connection->uid))
{
// Remove o mapeamento da conexão ao desconectar
unset($worker->uidConnections[$connection->uid]);
}
};
// Envia dados para todos os usuários autenticados
function broadcast($message)
{
global $worker;
foreach($worker->uidConnections as $connection)
{
$connection->send($message);
}
}
// Envia dados para um uid específico
function sendMessageByUid($uid, $message)
{
global $worker;
if(isset($worker->uidConnections[$uid]))
{
$connection = $worker->uidConnections[$uid];
$connection->send($message);
}
}
// Executa todos os workers (apesar de atualmente apenas um estar definido)
Worker::runAll();
Observação:
O exemplo acima permite a transmissão direcionada por uid e, embora seja um único processo, é capaz de suportar cerca de 100.000 usuários online sem problemas.
Atenção: Esse exemplo permite apenas um único processo, ou seja, $worker->count deve ser 1. Para suportar vários processos ou um cluster de servidores, é necessário utilizar o componente Channel para comunicação entre os processos. O desenvolvimento também é bastante simples e pode ser consultado na seção Exemplo de transmissão em cluster usando o componente Channel.
Se desejar enviar mensagens para clientes em outros sistemas, consulte a seção Enviar em outros projetos