hyperf-chat/app/Service/SocketClientService.php

146 lines
3.9 KiB
PHP
Raw Normal View History

2020-11-07 22:57:10 +08:00
<?php
namespace App\Service;
2021-05-21 22:56:42 +08:00
use App\Cache\ServerRunID;
2020-11-07 22:57:10 +08:00
use Hyperf\Redis\Redis;
/**
* Socket客户端ID服务
*
* @package App\Service
*/
2020-11-29 14:44:11 +08:00
class SocketClientService
2020-11-07 22:57:10 +08:00
{
/**
* fd与用户绑定(使用hash 做处理)
*/
2020-11-08 17:10:05 +08:00
const BIND_FD_TO_USER = 'ws:fd:user';
2020-11-07 22:57:10 +08:00
/**
* 使用集合做处理
*/
2020-11-08 17:10:05 +08:00
const BIND_USER_TO_FDS = 'ws:user:fds';
2020-11-07 22:57:10 +08:00
/**
* @var Redis
*/
private $redis;
2020-11-08 17:10:05 +08:00
public function __construct()
{
$this->redis = container()->get(Redis::class);
}
2020-11-07 22:57:10 +08:00
/**
* 客户端fd与用户ID绑定关系
*
2021-04-20 16:30:57 +08:00
* @param int $fd 客户端fd
* @param int $user_id 用户ID
* @param string $run_id 服务运行ID默认当前服务ID
2020-11-07 22:57:10 +08:00
*/
public function bindRelation(int $fd, int $user_id, $run_id = SERVER_RUN_ID)
{
$this->redis->multi();
$this->redis->hSet(sprintf('%s:%s', self::BIND_FD_TO_USER, $run_id), (string)$fd, (string)$user_id);
$this->redis->sadd(sprintf('%s:%s:%s', self::BIND_USER_TO_FDS, $run_id, $user_id), $fd);
$this->redis->exec();
}
/**
* 解除指定的客户端fd与用户绑定关系
*
2021-04-20 16:30:57 +08:00
* @param int $fd 客户端ID
2020-11-07 22:57:10 +08:00
* @param string $run_id 服务运行ID默认当前服务ID
*/
public function removeRelation(int $fd, $run_id = SERVER_RUN_ID)
{
$user_id = $this->findFdUserId($fd) | 0;
$this->redis->hdel(sprintf('%s:%s', self::BIND_FD_TO_USER, $run_id), (string)$fd);
$this->redis->srem(sprintf('%s:%s:%s', self::BIND_USER_TO_FDS, $run_id, $user_id), $fd);
}
/**
2020-11-08 17:10:05 +08:00
* 检测用户当前是否在线(指定运行服务器)
2020-11-07 22:57:10 +08:00
*
2021-04-20 16:30:57 +08:00
* @param int $user_id 用户ID
* @param string $run_id 服务运行ID默认当前服务ID
2020-11-07 22:57:10 +08:00
* @return bool
*/
public function isOnline(int $user_id, $run_id = SERVER_RUN_ID): bool
{
2021-04-22 16:14:34 +08:00
return (bool)$this->redis->scard(sprintf('%s:%s:%s', self::BIND_USER_TO_FDS, $run_id, $user_id));
2020-11-07 22:57:10 +08:00
}
2020-11-08 17:10:05 +08:00
/**
* 检测用户当前是否在线(查询所有在线服务器)
*
2021-04-20 16:30:57 +08:00
* @param int $user_id 用户ID
2020-11-08 17:10:05 +08:00
* @param array $run_ids 服务运行ID
* @return bool
*/
public function isOnlineAll(int $user_id, array $run_ids = [])
{
2021-05-21 22:56:42 +08:00
$run_ids = $run_ids ?: ServerRunID::getInstance()->getServerRunIdAll();
2020-11-08 17:10:05 +08:00
2020-11-09 17:41:22 +08:00
foreach ($run_ids as $run_id => $time) {
2020-11-08 17:10:05 +08:00
if ($this->isOnline($user_id, $run_id)) return true;
}
return false;
}
2020-11-07 22:57:10 +08:00
/**
* 查询客户端fd对应的用户ID
*
2021-04-20 16:30:57 +08:00
* @param int $fd 客户端ID
2020-11-07 22:57:10 +08:00
* @param string $run_id 服务运行ID默认当前服务ID
* @return int
*/
public function findFdUserId(int $fd, $run_id = SERVER_RUN_ID)
{
return $this->redis->hget(sprintf('%s:%s', self::BIND_FD_TO_USER, $run_id), (string)$fd) ?: 0;
}
/**
* 查询用户的客户端fd集合(用户可能存在多端登录)
*
2021-04-20 16:30:57 +08:00
* @param int $user_id 用户ID
* @param string $run_id 服务运行ID默认当前服务ID
2020-11-08 22:58:17 +08:00
* @return array
2020-11-07 22:57:10 +08:00
*/
public function findUserFds(int $user_id, $run_id = SERVER_RUN_ID)
{
2020-11-29 14:44:11 +08:00
$arr = $this->redis->smembers(sprintf('%s:%s:%s', self::BIND_USER_TO_FDS, $run_id, $user_id));
return $arr ? array_map(function ($fd) {
return (int)$fd;
}, $arr) : [];
2020-11-08 17:10:05 +08:00
}
2020-11-07 22:57:10 +08:00
/**
* 清除绑定缓存的信息
*
2020-11-08 17:10:05 +08:00
* @param string $run_id 服务运行ID
2020-11-07 22:57:10 +08:00
*/
2020-11-08 17:10:05 +08:00
public function removeRedisCache(string $run_id)
2020-11-07 22:57:10 +08:00
{
2020-11-08 17:10:05 +08:00
$this->redis->del(sprintf('%s:%s', self::BIND_FD_TO_USER, $run_id));
$prefix = sprintf('%s:%s', self::BIND_USER_TO_FDS, $run_id);
2021-05-21 22:56:42 +08:00
ServerRunID::getInstance()->rem($run_id);
2020-11-08 17:10:05 +08:00
2020-11-07 22:57:10 +08:00
$iterator = null;
while (true) {
$keys = $this->redis->scan($iterator, "{$prefix}*");
2020-11-08 17:10:05 +08:00
if ($keys === false) return;
2020-11-07 22:57:10 +08:00
if (!empty($keys)) {
$this->redis->del(...$keys);
}
}
}
2020-11-08 17:10:05 +08:00
}