請(qǐng)教下各位大神,下方是我寫(xiě)的偽邏輯,看起來(lái)沒(méi)問(wèn)題,但實(shí)際設(shè)備上下線頻繁時(shí),在線狀況是錯(cuò)誤的,調(diào)試后發(fā)現(xiàn)是onMessage
中Gateway::closeClient($id);
的操作觸發(fā)onClose
,是在onMessage
后續(xù)將設(shè)備設(shè)置為在線之后。
也就是說(shuō),我在設(shè)備上線后,手動(dòng)斷開(kāi)老的連接,將狀態(tài)設(shè)置為離線,再將狀態(tài)設(shè)置為在線的操作由于onClose
并不會(huì)馬上執(zhí)行導(dǎo)致順序反轉(zhuǎn)
function onMessage($client_id, $data){
//獲取設(shè)備發(fā)送的業(yè)務(wù)ID
$id = $data['id'];
//如果之前已經(jīng)有在線的則踢掉,如意外掉線,心跳未斷掉的情況下
$ids = Gateway::getClientIdByUid($id);
foreach ($ids as $id) {
Gateway::closeClient($id);
}
//存入$_SESSION,在onClose時(shí)判斷存在ID則離線
$_SESSION['id'] = $id;
//綁定client_id和業(yè)務(wù)ID
Gateway::bindUid($client_id, $id);
//持久化在線離線狀態(tài),例Redis
Redis::hSet($id,'online', 1);
//推送設(shè)備在線至客戶端
Gateway::sendToGroup($id, 'online|1');
}
function onClose($client_id){
if(isset($_SESSION['id'])){
$id = $_SESSION['id']
Redis::hSet($id,'online', 0);
Gateway::sendToGroup($id, 'online|0');
}
}
把這段去掉呢
去掉的話如果同一個(gè)設(shè)備老的連接還存在,新的連接上線(如意外掉線,沒(méi)主動(dòng)斷掉連接),會(huì)導(dǎo)致新的連接設(shè)置成了在線后因?yàn)槔系倪B接心跳停止又設(shè)置成離線
我這里是想先把老連接主動(dòng)切斷
是的,在心跳完全結(jié)束前,新的連接連進(jìn)來(lái)會(huì)設(shè)置為在線,心跳結(jié)束后在onClose又會(huì)設(shè)置成離線
我這邊client_id是存庫(kù)的 新連接上來(lái) client_id替換舊client_id 舊client_id 離線 處理離線會(huì)查不到之前的設(shè)備
理解,但我是根據(jù)業(yè)務(wù)ID,設(shè)備每次連接時(shí)ID都是相同的,所以我想先把未斷掉心跳的連接主動(dòng)切斷后再設(shè)置成上線
打算在onClose
里isUidOnline
,如果用業(yè)務(wù)ID能查到有在線的連接,就不設(shè)置為離線。
不知道在onClose
里自己算不算在線連接,如果算話改用getClientIdByUid,感覺(jué)沒(méi)問(wèn)題。
各位有沒(méi)有更優(yōu)雅的方法~