Workermanで特定のクライアントにデータを送信する方法

workerを使用してサーバーを構築し、GatewayWorkerを使用せず、特定のユーザーにメッセージをプッシュするにはどうすればいいですか?

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

// 1234ポートをリッスンするworkerコンテナを初期化
$worker = new Worker('websocket://workerman.net:1234');
// ====ここでプロセス数は必ず1に設定する必要があります====
$worker->count = 1;
// uidからconnectionへのマッピングを保存するための新しいプロパティを追加
$worker->uidConnections = array();
// クライアントからメッセージが送信された際に実行されるコールバック関数
$worker->onMessage = function(TcpConnection $connection, $data)
{
    global $worker;
    // 現在のクライアントが認証済みかどうかを判断(uidが設定されているか確認)
    if(!isset($connection->uid))
    {
       // 認証されていない場合、最初のパッケージをuidとして扱う(ここではデモのため、実際の認証は行っていません)
       $connection->uid = $data;
       /* uidからconnectionへのマッピングを保存することにより、uidを介してconnectionを簡単に検索でき、
        * 特定のuidにデータをプッシュすることが可能になります
        */
       $worker->uidConnections[$connection->uid] = $connection;
       return $connection->send('login success, your uid is ' . $connection->uid);
    }
    // その他のロジック、特定のuidに対して送信 または 全体にブロードキャスト
    // メッセージフォーマットが uid: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);
    }
}

// 全てのworkerを実行(実際には現在1つだけが定義されています)
Worker::runAll();

説明:

上記の例では、uidに対してプッシュが可能で、単一プロセスですが、10万人のオンラインをサポートすることが問題ありません。

注意:この例はプロセスが単一であるため、$worker->countは必ず1でなければなりません。マルチプロセスやサーバークラスターをサポートするには、Channelコンポーネントを使用してプロセス間通信を行う必要があり、開発も非常に簡単です。Channelコンポーネントのクラスター推送の例を参照してください。

他のシステムでクライアントにメッセージをプッシュしたい場合は、他のプロジェクトでプッシュのセクションを参照してください。