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コンポーネントのクラスター推送の例を参照してください。
他のシステムでクライアントにメッセージをプッシュしたい場合は、他のプロジェクトでプッシュのセクションを参照してください。