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