Как отправить данные конкретному клиенту в Workerman

Как реализовать отправку сообщений конкретному пользователю, используя worker в качестве сервера, без GatewayWorker?

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

// Инициализация контейнера worker, прослушивающего порт 1234
$worker = new Worker('websocket://workerman.net:1234');
// ====Количество процессов обязательно должно быть установлено в 1====
$worker->count = 1;
// Новое свойство для сохранения сопоставления uid с соединением (uid - это идентификатор пользователя или уникальный идентификатор клиента)
$worker->uidConnections = array();
// Функция обратного вызова, которая выполняется, когда клиент отправляет сообщение
$worker->onMessage = function(TcpConnection $connection, $data)
{
    global $worker;
    // Проверка, прошел ли текущий клиент аутентификацию, т.е. установлен ли uid
    if(!isset($connection->uid))
    {
       // Если нет, используйте первый пакет как uid (для удобства демонстрации аутентификация не выполнена)
       $connection->uid = $data;
       /* Сохранение сопоставления uid с соединением, чтобы удобно находить соединение по uid,
        * позволяя отправлять данные конкретному uid
        */
       $worker->uidConnections[$connection->uid] = $connection;
       return $connection->send('вход успешен, ваш uid: ' . $connection->uid);
    }
    // Другие логики, отправка сообщения конкретному uid или глобальная рассылка
    // Предположим, что формат сообщения - uid:message, это отправка message для uid
    // uid равен all, что означает глобальную рассылку
    list($recv_uid, $message) = explode(':', $data);
    // Глобальная рассылка
    if($recv_uid == 'all')
    {
        broadcast($message);
    }
    // Отправка конкретному uid
    else
    {
        sendMessageByUid($recv_uid, $message);
    }
};

// Когда клиентское соединение разрывается
$worker->onClose = function(TcpConnection $connection)
{
    global $worker;
    if(isset($connection->uid))
    {
        // Удаляем сопоставление при разрыве соединения
        unset($worker->uidConnections[$connection->uid]);
    }
};

// Отправка данных всем аутентифицированным пользователям
function broadcast($message)
{
   global $worker;
   foreach($worker->uidConnections as $connection)
   {
        $connection->send($message);
   }
}

// Отправка данных конкретному uid
function sendMessageByUid($uid, $message)
{
    global $worker;
    if(isset($worker->uidConnections[$uid]))
    {
        $connection = $worker->uidConnections[$uid];
        $connection->send($message);
    }
}

// Запуск всех workers (в данный момент определен только один)
Worker::runAll();

说明:

В приведенном примере можно отправлять сообщения по uid, несмотря на то, что это однопроцессный вариант, поддерживать 100,000 онлайн-пользователей не составит труда.

Обратите внимание, что этот пример может работать только в однопроцессной моде, то есть $worker->count должен быть равен 1. Для поддержки многопроцессности или серверного кластера потребуется компонент Channel для межпроцессного взаимодействия, разработка также очень проста, вы можете ознакомиться с примером рассылки с помощью компонента Channel.

Если вы хотите отправлять сообщения клиенту из других систем, вы можете ознакомиться с разделом отправки в других проектах