请教下各位大神,下方是我写的伪逻辑,看起来没问题,但实际设备上下线频繁时,在线状况是错误的,调试后发现是onMessage
中Gateway::closeClient($id);
的操作触发onClose
,是在onMessage
后续将设备设置为在线之后。
也就是说,我在设备上线后,手动断开老的连接,将状态设置为离线,再将状态设置为在线的操作由于onClose
并不会马上执行导致顺序反转
function onMessage($client_id, $data){
//获取设备发送的业务ID
$id = $data['id'];
//如果之前已经有在线的则踢掉,如意外掉线,心跳未断掉的情况下
$ids = Gateway::getClientIdByUid($id);
foreach ($ids as $id) {
Gateway::closeClient($id);
}
//存入$_SESSION,在onClose时判断存在ID则离线
$_SESSION['id'] = $id;
//绑定client_id和业务ID
Gateway::bindUid($client_id, $id);
//持久化在线离线状态,例Redis
Redis::hSet($id,'online', 1);
//推送设备在线至客户端
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');
}
}
把这段去掉呢
去掉的话如果同一个设备老的连接还存在,新的连接上线(如意外掉线,没主动断掉连接),会导致新的连接设置成了在线后因为老的连接心跳停止又设置成离线
我这里是想先把老连接主动切断
没主动断掉连接 还掉线 你这个掉线怎么说
比如设备那里突然断电是不会在断电前主动断掉连接的,上电后是一条新的连接
那之前那个连接就不发心跳了, 服务端回主动踢掉了
是的,在心跳完全结束前,新的连接连进来会设置为在线,心跳结束后在onClose又会设置成离线
我这边client_id是存库的 新连接上来 client_id替换旧client_id 旧client_id 离线 处理离线会查不到之前的设备
理解,但我是根据业务ID,设备每次连接时ID都是相同的,所以我想先把未断掉心跳的连接主动切断后再设置成上线
业务id搭配 client_id 处理 我感觉会好些
感谢回复,我再研究一下~
打算在
onClose
里isUidOnline
,如果用业务ID能查到有在线的连接,就不设置为离线。不知道在
onClose
里自己算不算在线连接,如果算话改用getClientIdByUid,感觉没问题。各位有没有更优雅的方法~