2020-11-02 22:45:37 +08:00
|
|
|
|
<?php
|
|
|
|
|
declare(strict_types=1);
|
|
|
|
|
|
|
|
|
|
namespace App\Controller;
|
|
|
|
|
|
2020-11-07 22:57:10 +08:00
|
|
|
|
use Hyperf\Di\Annotation\Inject;
|
2020-11-02 22:45:37 +08:00
|
|
|
|
use Hyperf\Contract\OnCloseInterface;
|
|
|
|
|
use Hyperf\Contract\OnMessageInterface;
|
|
|
|
|
use Hyperf\Contract\OnOpenInterface;
|
2020-11-07 22:57:10 +08:00
|
|
|
|
use Phper666\JWTAuth\JWT;
|
2020-11-02 22:45:37 +08:00
|
|
|
|
use Swoole\Http\Request;
|
|
|
|
|
use Swoole\Websocket\Frame;
|
2020-11-03 14:07:54 +08:00
|
|
|
|
use Hyperf\Amqp\Producer;
|
2020-11-07 22:57:10 +08:00
|
|
|
|
use Swoole\Http\Response;
|
|
|
|
|
use Swoole\WebSocket\Server;
|
|
|
|
|
use App\Traits\WebSocketTrait;
|
|
|
|
|
use App\Service\SocketFDService;
|
2020-11-22 23:10:00 +08:00
|
|
|
|
use App\Service\MessageHandleService;
|
|
|
|
|
use App\Service\SocketRoomService;
|
|
|
|
|
use App\Model\Group\UsersGroupMember;
|
|
|
|
|
use App\Amqp\Producer\ChatMessageProducer;
|
2020-11-03 14:07:54 +08:00
|
|
|
|
|
2020-11-07 22:57:10 +08:00
|
|
|
|
/**
|
|
|
|
|
* Class WebSocketController
|
|
|
|
|
* @package App\Controller
|
|
|
|
|
*/
|
2020-11-02 22:45:37 +08:00
|
|
|
|
class WebSocketController implements OnMessageInterface, OnOpenInterface, OnCloseInterface
|
|
|
|
|
{
|
2020-11-07 22:57:10 +08:00
|
|
|
|
use WebSocketTrait;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @Inject
|
|
|
|
|
* @var JWT
|
|
|
|
|
*/
|
|
|
|
|
private $jwt;
|
|
|
|
|
|
2020-11-20 19:17:11 +08:00
|
|
|
|
/**
|
|
|
|
|
* @Inject
|
|
|
|
|
* @var Producer
|
|
|
|
|
*/
|
|
|
|
|
private $producer;
|
|
|
|
|
|
2020-11-07 22:57:10 +08:00
|
|
|
|
/**
|
|
|
|
|
* @inject
|
|
|
|
|
* @var SocketFDService
|
|
|
|
|
*/
|
|
|
|
|
private $socketFDService;
|
|
|
|
|
|
2020-11-21 19:53:01 +08:00
|
|
|
|
/**
|
|
|
|
|
* @inject
|
|
|
|
|
* @var SocketRoomService
|
|
|
|
|
*/
|
|
|
|
|
private $socketRoomService;
|
|
|
|
|
|
2020-11-22 23:10:00 +08:00
|
|
|
|
/**
|
|
|
|
|
* @inject
|
|
|
|
|
* @var MessageHandleService
|
|
|
|
|
*/
|
|
|
|
|
private $messageHandleService;
|
|
|
|
|
|
|
|
|
|
const EVENTS = [
|
|
|
|
|
'event_talk' => 'onTalk',
|
|
|
|
|
'event_keyboard' => 'onKeyboard',
|
|
|
|
|
];
|
|
|
|
|
|
2020-11-07 22:57:10 +08:00
|
|
|
|
/**
|
|
|
|
|
* 连接创建成功回调事件
|
|
|
|
|
*
|
|
|
|
|
* @param Response|Server $server
|
|
|
|
|
* @param Request $request
|
|
|
|
|
*/
|
|
|
|
|
public function onOpen($server, Request $request): void
|
2020-11-02 22:45:37 +08:00
|
|
|
|
{
|
2020-11-07 22:57:10 +08:00
|
|
|
|
$token = $request->get['token'] ?? '';
|
|
|
|
|
$userInfo = $this->jwt->getParserData($token);
|
2020-11-21 19:53:01 +08:00
|
|
|
|
stdout_log()->notice("用户连接信息 : user_id:{$userInfo['user_id']} | fd:{$request->fd} 时间:" . date('Y-m-d H:i:s'));
|
2020-11-07 22:57:10 +08:00
|
|
|
|
|
2020-11-22 23:10:00 +08:00
|
|
|
|
// 判断是否存在异地登录
|
|
|
|
|
$isOnline = $this->socketFDService->isOnlineAll(intval($userInfo['user_id']));
|
|
|
|
|
|
2020-11-07 22:57:10 +08:00
|
|
|
|
// 绑定fd与用户关系
|
|
|
|
|
$this->socketFDService->bindRelation($request->fd, $userInfo['user_id']);
|
2020-11-03 14:07:54 +08:00
|
|
|
|
|
2020-11-21 19:53:01 +08:00
|
|
|
|
// 加入群聊
|
|
|
|
|
$groupIds = UsersGroupMember::getUserGroupIds($userInfo['user_id']);
|
|
|
|
|
foreach ($groupIds as $group_id) {
|
|
|
|
|
$this->socketRoomService->addRoomMember($userInfo['user_id'], $group_id);
|
|
|
|
|
}
|
2020-11-22 23:10:00 +08:00
|
|
|
|
|
|
|
|
|
if (!$isOnline) {
|
|
|
|
|
// 推送消息至队列
|
|
|
|
|
$this->producer->produce(
|
|
|
|
|
new ChatMessageProducer('event_online_status', [
|
|
|
|
|
'user_id' => $userInfo['user_id'],
|
|
|
|
|
'status' => 1,
|
|
|
|
|
'notify' => '好友上线通知...'
|
|
|
|
|
])
|
|
|
|
|
);
|
|
|
|
|
}
|
2020-11-02 22:45:37 +08:00
|
|
|
|
}
|
|
|
|
|
|
2020-11-07 22:57:10 +08:00
|
|
|
|
/**
|
|
|
|
|
* 消息接收回调事件
|
|
|
|
|
*
|
|
|
|
|
* @param Response|Server $server
|
|
|
|
|
* @param Frame $frame
|
|
|
|
|
*/
|
|
|
|
|
public function onMessage($server, Frame $frame): void
|
2020-11-02 22:45:37 +08:00
|
|
|
|
{
|
2020-11-08 22:58:17 +08:00
|
|
|
|
// 判断是否为心跳检测
|
|
|
|
|
if ($frame->data == 'PING') return;
|
|
|
|
|
|
2020-11-21 19:53:01 +08:00
|
|
|
|
[$event, $data] = array_values(json_decode($frame->data, true));
|
|
|
|
|
|
2020-11-22 23:10:00 +08:00
|
|
|
|
if (isset(self::EVENTS[$event])) {
|
|
|
|
|
$this->messageHandleService->{self::EVENTS[$event]}($server, $frame, $data);
|
2020-11-21 19:53:01 +08:00
|
|
|
|
return;
|
|
|
|
|
}
|
2020-11-02 22:45:37 +08:00
|
|
|
|
}
|
|
|
|
|
|
2020-11-07 22:57:10 +08:00
|
|
|
|
/**
|
|
|
|
|
* 连接创建成功回调事件
|
|
|
|
|
*
|
|
|
|
|
* @param Response|\Swoole\Server $server
|
|
|
|
|
* @param int $fd
|
|
|
|
|
* @param int $reactorId
|
|
|
|
|
*/
|
|
|
|
|
public function onClose($server, int $fd, int $reactorId): void
|
2020-11-02 22:45:37 +08:00
|
|
|
|
{
|
2020-11-08 22:58:17 +08:00
|
|
|
|
$user_id = $this->socketFDService->findFdUserId($fd);
|
|
|
|
|
|
2020-11-22 23:10:00 +08:00
|
|
|
|
// stdout_log()->notice("客户端FD:{$fd} 已关闭连接 ,用户ID为【{$user_id}】,关闭时间:" . date('Y-m-d H:i:s'));
|
2020-11-08 22:58:17 +08:00
|
|
|
|
|
2020-11-07 22:57:10 +08:00
|
|
|
|
// 解除fd关系
|
|
|
|
|
$this->socketFDService->removeRelation($fd);
|
2020-11-08 22:58:17 +08:00
|
|
|
|
|
2020-11-09 17:41:22 +08:00
|
|
|
|
// 判断是否存在异地登录
|
|
|
|
|
$isOnline = $this->socketFDService->isOnlineAll(intval($user_id));
|
2020-11-22 23:10:00 +08:00
|
|
|
|
// ... 不存在异地登录,推送下线通知消息
|
2020-11-09 17:41:22 +08:00
|
|
|
|
if (!$isOnline) {
|
2020-11-22 23:10:00 +08:00
|
|
|
|
// 推送消息至队列
|
|
|
|
|
$this->producer->produce(
|
|
|
|
|
new ChatMessageProducer('event_online_status', [
|
|
|
|
|
'user_id' => $user_id,
|
|
|
|
|
'status' => 0,
|
|
|
|
|
'notify' => '好友离线通知通知...'
|
|
|
|
|
])
|
|
|
|
|
);
|
2020-11-09 17:41:22 +08:00
|
|
|
|
}
|
2020-11-02 22:45:37 +08:00
|
|
|
|
}
|
|
|
|
|
}
|