Comment envoyer des données à un client spécifique dans Workerman

Comment réaliser une notification à un utilisateur spécifique en utilisant un worker comme serveur sans GatewayWorker ?

<?php
use Workerman\Worker;
use Workerman\Connection\TcpConnection;
require_once __DIR__ . '/vendor/autoload.php';

// Initialiser un conteneur worker, écouter le port 1234
$worker = new Worker('websocket://workerman.net:1234');
// ==== le nombre de processus doit être absolument défini à 1 ====
$worker->count = 1;
// Ajouter un nouvel attribut pour stocker le mapping uid vers connection (uid est l'identifiant utilisateur ou l'identifiant unique du client)
$worker->uidConnections = array();
// Fonction de rappel exécutée lorsque un client envoie un message
$worker->onMessage = function(TcpConnection $connection, $data)
{
    global $worker;
    // Vérifier si le client actuel a déjà été authentifié, c'est-à-dire s'il a un uid défini
    if(!isset($connection->uid))
    {
       // Si non authentifié, considérer le premier paquet comme uid (ici pour faciliter la démonstration, aucune véritable vérification n'est effectuée)
       $connection->uid = $data;
       /* Sauvegarder le mapping uid vers connection, cela permet de retrouver facilement la connection par uid,
        * permettant ainsi de pousser des données ciblées à un uid spécifique
        */
       $worker->uidConnections[$connection->uid] = $connection;
       return $connection->send('connexion réussie, votre uid est ' . $connection->uid);
    }
    // Autres logiques, envoyer à un uid spécifique ou diffusion globale
    // Supposons que le format du message soit uid:message pour envoyer un message à uid
    // uid étant all pour une diffusion globale
    list($recv_uid, $message) = explode(':', $data);
    // Diffusion globale
    if($recv_uid == 'all')
    {
        broadcast($message);
    }
    // Envoyer à un uid spécifique
    else
    {
        sendMessageByUid($recv_uid, $message);
    }
};

// Lorsque un client se déconnecte
$worker->onClose = function(TcpConnection $connection)
{
    global $worker;
    if(isset($connection->uid))
    {
        // Supprimer le mapping lors de la déconnexion
        unset($worker->uidConnections[$connection->uid]);
    }
};

// Pousser des données à tous les utilisateurs authentifiés
function broadcast($message)
{
   global $worker;
   foreach($worker->uidConnections as $connection)
   {
        $connection->send($message);
   }
}

// Pousser des données à un uid spécifique
function sendMessageByUid($uid, $message)
{
    global $worker;
    if(isset($worker->uidConnections[$uid]))
    {
        $connection = $worker->uidConnections[$uid];
        $connection->send($message);
    }
}

// Exécuter tous les workers (en réalité, un seul est défini ici)
Worker::runAll();

Remarque :

L'exemple ci-dessus permet de pousser des messages par rapport à un uid, même si c'est un processus unique, il peut facilement gérer 100 000 connexions en ligne.

Attention, cet exemple ne fonctionne qu'avec un seul processus, c'est-à-dire que $worker->count doit être 1. Pour prendre en charge plusieurs processus ou un cluster de serveurs, il est nécessaire d'utiliser le composant Channel pour réaliser la communication entre processus, le développement est également très simple, vous pouvez vous référer à la section Exemple de diffusion dans un cluster avec le composant Channel.

Si vous souhaitez pousser des messages aux clients depuis d'autres systèmes, vous pouvez consulter la section Pousser dans d'autres projets.