目前我用worker來做服務(wù)器,沒有用GatewayWorker,請問walkor大哥,如何實現(xiàn)向指定用戶推送消息?
以下是我的代碼:
$client_id = '';
$worker->onConnection( $connection ){
global $client_id;
$client_id = $connection->id;
};
$worker->onMessage( $connection, $data ){
global $client_id;
foreach( $connection->worker->connections as $con ){
if( $con->id == $client_id ){
$con->send( $data );
break;
}
}
};
注:在觸發(fā)onConnect的時候,取得ClientID,然后在onMessage內(nèi)將ClientID和用戶其他資料綁定并儲存到數(shù)據(jù)庫。上述代碼臨時寫出來的,我實際的需求是,基于worker向指定ClientID的在線用戶推送消息,上面代碼可能寫成向當前用戶推送了。
<?php
use Workerman\Worker;
require_once './Workerman/Autoloader.php';
// 初始化一個worker容器,監(jiān)聽1234端口
$worker = new Worker('websocket://workerman.net:1234');
// 進程數(shù)設(shè)置為1
$worker->count = 1;
// 新增加一個屬性,用來保存uid到connection的映射
$worker->uidConnections = array();
// 當有客戶端發(fā)來消息時執(zhí)行的回調(diào)函數(shù)
$worker->onMessage = function($connection, $data)use($worker)
{
// 判斷當前客戶端是否已經(jīng)驗證,既是否設(shè)置了uid
if(!isset($connection->uid))
{
// 沒驗證的話把第一個包當做uid(這里為了方便演示,沒做真正的驗證)
$connection->uid = $data;
/* 保存uid到connection的映射,這樣可以方便的通過uid查找connection,
* 實現(xiàn)針對特定uid推送數(shù)據(jù)
*/
$worker->uidConnections = $connection;
return $connection->send('login success, your uid is ' . $connection->uid);
}
// 其它羅輯,針對某個uid發(fā)送 或者 全局廣播
// 假設(shè)消息格式為 uid:message 時是對 uid 發(fā)送 message
// uid 為 all 時是全局廣播
list($recv_uid, $message) = explode(':', $data);
// 全局廣播
if($recv_uid == 'all')
{
broadcast($message);
}
// 給特定uid發(fā)送
else
{
sendMessageByUid($recv_uid, $message);
}
};
// 當有客戶端連接斷開時
$worker->onClose = function($connection)use($worker)
{
global $worker;
if(isset($connection->uid))
{
// 連接斷開時刪除映射
unset($worker->uidConnections);
}
};
// 向所有驗證的用戶推送數(shù)據(jù)
function broadcast($message)
{
global $worker;
foreach($worker->uidConnections as $connection)
{
$connection->send($message);
}
}
// 針對uid推送數(shù)據(jù)
function sendMessageByUid($uid, $message)
{
global $worker;
if(isset($worker->uidConnections))
{
$connection = $worker->uidConnections;
$connection->send($message);
}
}
// 運行所有的worker(其實當前只定義了一個)
Worker::runAll();
可以針對uid推送了,雖然是單進程,但是支持個1W在線是沒問題的
$worker->onMessage = function( $connection, $data ){
if( $data數(shù)據(jù)不合法時 ){
$connection->close();
}
}
使用類似代碼時,貌似是全體在線用戶均會觸發(fā)close事件。