166 lines
5.2 KiB
PHP
166 lines
5.2 KiB
PHP
<?php
|
||
|
||
namespace app\event;
|
||
/**
|
||
* 用于检测业务代码死循环或者长时间阻塞等问题
|
||
* 如果发现业务卡死,可以将下面declare打开(去掉//注释),并执行php start.php reload
|
||
* 然后观察一段时间workerman.log看是否有process_timeout异常
|
||
*/
|
||
//declare(ticks=1);
|
||
|
||
use app\entity\gateway\ws\OutMessage;
|
||
use app\entity\gateway\ws\PutMessage;
|
||
use app\entity\SysRole;
|
||
use app\entity\SysUser;
|
||
use app\enum\gateway\WsEventEnum;
|
||
use app\enum\gateway\WsTypeEnum;
|
||
use app\service\admin\LoginService;
|
||
use app\service\GatewayClientService;
|
||
use think\exception\ValidateException;
|
||
use think\facade\Event;
|
||
|
||
class SysGatewayEvent
|
||
{
|
||
public static function onMessage(string $client_id, string $message): void
|
||
{
|
||
// 1. 客户端应该传递标准的json数据
|
||
$message_data = json_decode($message, true);
|
||
if (!$message_data) {
|
||
return;
|
||
}
|
||
// 2. 封装进来的消息体
|
||
$put = new PutMessage(
|
||
$client_id,
|
||
isset($message_data['type']) ? (string)$message_data['type'] : '',
|
||
isset($message_data['event']) ? (string)$message_data['event'] : '',
|
||
isset($message_data['data']) ? (array)$message_data['data'] : []
|
||
);
|
||
/*
|
||
* 客户端登录
|
||
*/
|
||
if ($put->type == WsTypeEnum::System && $put->event == WsEventEnum::Login) {
|
||
self::authEvent($put);
|
||
return;
|
||
}
|
||
$isLogin = $put->login($_SESSION['user_id'] ?? 0,
|
||
$_SESSION['user_type'] ?? '',
|
||
$_SESSION['client'] ?? []
|
||
);
|
||
if (!$isLogin) {
|
||
echo "用户未登录\r\n";
|
||
// 未登录
|
||
return;
|
||
}
|
||
|
||
|
||
// 3. 调度: 根据类型执行不同的业务
|
||
switch ($put->type) {
|
||
// 客户端回应服务端的心跳
|
||
case WsTypeEnum::Pong:
|
||
break;
|
||
// 系统类型组操作
|
||
case WsTypeEnum::System:
|
||
switch ($put->event) {
|
||
case WsEventEnum::Lock_Client:
|
||
/**
|
||
* 触发后续其他事件
|
||
*/
|
||
Event::trigger("gateway.lockClient", [$put]);
|
||
break;
|
||
}
|
||
return;
|
||
}
|
||
}
|
||
|
||
public static function onClose(string $client_id)
|
||
{
|
||
echo "客户端:{$client_id},关闭了\r\n";
|
||
// 客户端离线的相关逻辑操作
|
||
if (isset($_SESSION['group_list']) && is_array($_SESSION['group_list'])) {
|
||
foreach ($_SESSION['group_list'] as $group) {
|
||
/*
|
||
* 客户端退出了某个房间
|
||
*/
|
||
GatewayClientService::sendToGroup($group, new OutMessage(
|
||
WsTypeEnum::System,
|
||
WsEventEnum::Client_quit_room,
|
||
));
|
||
}
|
||
}
|
||
/**
|
||
* 触发后续其他事件
|
||
*/
|
||
Event::trigger("gateway.clientClose", [$client_id]);
|
||
}
|
||
|
||
private static function authEvent(PutMessage $put): void
|
||
{
|
||
$token = $put->get('token', '');
|
||
$clientVersion = $put->get('clientVersion', '');
|
||
$clientName = $put->get('clientName', '');
|
||
$clientId = $put->get('clientId', '');
|
||
|
||
try {
|
||
$token = str_replace('Bearer ', '', $token);
|
||
$loginSrv = new LoginService();
|
||
$auth = $loginSrv->checkUserAccessToken($token);
|
||
} catch (ValidateException $e) {
|
||
// 校验失败
|
||
var_dump('E1.登录凭证校验失败: '.$e->getMessage());
|
||
return;
|
||
}
|
||
var_dump($auth->userId);
|
||
/**
|
||
* 加入同角色房间
|
||
*/
|
||
$sysUser = SysUser::find($auth->userId);
|
||
if ($sysUser) {
|
||
var_dump('E1.用户数据不存在');
|
||
return;
|
||
}
|
||
|
||
// 登录
|
||
$put->login($auth->userId, $auth->userType->value, [
|
||
'id' => $clientId,
|
||
'name' => $clientName,
|
||
'version' => $clientVersion
|
||
]);
|
||
/**
|
||
* 记录登录凭证信息到$SESSION中
|
||
*/
|
||
$_SESSION['user_id'] = $put->userId;
|
||
$_SESSION['user_type'] = $put->userType;
|
||
$_SESSION['client'] = [
|
||
'id' => $put->getClientId(),
|
||
'name' => $put->getClientName(),
|
||
'version' => $put->getClientVersion()
|
||
];
|
||
/**
|
||
* 推送登录成功的消息到客户端
|
||
*/
|
||
GatewayClientService::sendToClient($put->wsClientId, new OutMessage(
|
||
WsTypeEnum::System,
|
||
WsEventEnum::Login_SUCCESS,
|
||
['userId' => $auth->userId]
|
||
));
|
||
/**
|
||
*
|
||
*/
|
||
GatewayClientService::bindUid($put->wsClientId, $auth->userId);
|
||
/**
|
||
* 加入已登录的用户公共大厅
|
||
*/
|
||
GatewayClientService::joinGroup($put->wsClientId, 'PUBLIC_ROOM');
|
||
/**
|
||
* 加入同角色的房间
|
||
*/
|
||
$sysUser->roles->each(function (SysRole $role) use ($put) {
|
||
GatewayClientService::joinGroup($put->wsClientId, "ROLE_{$role['id']}");
|
||
});
|
||
/**
|
||
* 触发后续其他事件
|
||
*/
|
||
Event::trigger("gateway.clientLogin", [$put, $sysUser]);
|
||
}
|
||
}
|