2020-11-02 22:45:37 +08:00
|
|
|
|
<?php
|
|
|
|
|
declare(strict_types=1);
|
2021-09-11 12:41:28 +08:00
|
|
|
|
|
2020-12-26 21:33:40 +08:00
|
|
|
|
/**
|
|
|
|
|
* This is my open source code, please do not use it for commercial applications.
|
|
|
|
|
* For the full copyright and license information,
|
|
|
|
|
* please view the LICENSE file that was distributed with this source code
|
|
|
|
|
*
|
|
|
|
|
* @author Yuandong<837215079@qq.com>
|
|
|
|
|
* @link https://github.com/gzydong/hyperf-chat
|
|
|
|
|
*/
|
2020-11-02 22:45:37 +08:00
|
|
|
|
|
|
|
|
|
namespace App\Controller;
|
|
|
|
|
|
2021-05-21 22:56:42 +08:00
|
|
|
|
use App\Cache\SocketRoom;
|
2021-07-28 23:08:07 +08:00
|
|
|
|
use App\Service\Group\GroupMemberService;
|
2021-07-08 19:09:06 +08:00
|
|
|
|
use App\Service\Message\ReceiveHandleService;
|
2020-11-07 22:57:10 +08:00
|
|
|
|
use Hyperf\Di\Annotation\Inject;
|
2021-07-20 23:12:18 +08:00
|
|
|
|
use App\Constants\TalkEventConstant;
|
2020-11-02 22:45:37 +08:00
|
|
|
|
use Hyperf\Contract\OnCloseInterface;
|
|
|
|
|
use Hyperf\Contract\OnMessageInterface;
|
|
|
|
|
use Hyperf\Contract\OnOpenInterface;
|
|
|
|
|
use Swoole\Http\Request;
|
|
|
|
|
use Swoole\Websocket\Frame;
|
2020-11-07 22:57:10 +08:00
|
|
|
|
use Swoole\Http\Response;
|
|
|
|
|
use Swoole\WebSocket\Server;
|
2020-11-29 14:44:11 +08:00
|
|
|
|
use App\Service\SocketClientService;
|
2021-07-20 23:12:18 +08:00
|
|
|
|
use App\Event\TalkEvent;
|
|
|
|
|
|
2020-11-03 14:07:54 +08:00
|
|
|
|
|
2020-11-07 22:57:10 +08:00
|
|
|
|
/**
|
|
|
|
|
* Class WebSocketController
|
2021-04-20 16:30:57 +08:00
|
|
|
|
*
|
2020-11-07 22:57:10 +08:00
|
|
|
|
* @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
|
|
|
|
/**
|
|
|
|
|
* @inject
|
2020-11-29 14:44:11 +08:00
|
|
|
|
* @var SocketClientService
|
2020-11-07 22:57:10 +08:00
|
|
|
|
*/
|
2021-07-09 19:40:43 +08:00
|
|
|
|
private $client;
|
2020-11-07 22:57:10 +08:00
|
|
|
|
|
2020-11-22 23:10:00 +08:00
|
|
|
|
/**
|
|
|
|
|
* @inject
|
2021-07-08 19:09:06 +08:00
|
|
|
|
* @var ReceiveHandleService
|
2020-11-22 23:10:00 +08:00
|
|
|
|
*/
|
2021-07-09 19:40:43 +08:00
|
|
|
|
private $receiveHandle;
|
2020-11-22 23:10:00 +08:00
|
|
|
|
|
2020-11-07 22:57:10 +08:00
|
|
|
|
/**
|
|
|
|
|
* 连接创建成功回调事件
|
|
|
|
|
*
|
|
|
|
|
* @param Response|Server $server
|
2021-04-20 16:30:57 +08:00
|
|
|
|
* @param Request $request
|
2020-11-07 22:57:10 +08:00
|
|
|
|
*/
|
|
|
|
|
public function onOpen($server, Request $request): void
|
2020-11-02 22:45:37 +08:00
|
|
|
|
{
|
2021-05-23 16:52:01 +08:00
|
|
|
|
// 当前连接的用户
|
|
|
|
|
$user_id = auth('jwt')->user()->getId();
|
2021-05-22 20:54:30 +08:00
|
|
|
|
|
2021-05-23 16:52:01 +08:00
|
|
|
|
stdout_log()->notice("用户连接信息 : user_id:{$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
|
|
|
|
// 判断是否存在异地登录
|
2021-07-09 19:40:43 +08:00
|
|
|
|
$isOnline = $this->client->isOnlineAll($user_id);
|
2020-11-22 23:10:00 +08:00
|
|
|
|
|
2020-12-26 21:33:40 +08:00
|
|
|
|
// 若开启单点登录,则主动关闭之前登录的连接
|
2020-12-02 15:14:29 +08:00
|
|
|
|
if ($isOnline) {
|
2021-08-29 22:24:45 +08:00
|
|
|
|
// todo 预留
|
2020-12-02 15:14:29 +08:00
|
|
|
|
}
|
|
|
|
|
|
2020-11-07 22:57:10 +08:00
|
|
|
|
// 绑定fd与用户关系
|
2021-07-09 19:40:43 +08:00
|
|
|
|
$this->client->bind($request->fd, $user_id);
|
2020-11-03 14:07:54 +08:00
|
|
|
|
|
2020-11-21 19:53:01 +08:00
|
|
|
|
// 加入群聊
|
2021-07-28 23:08:07 +08:00
|
|
|
|
$groupIds = di()->get(GroupMemberService::class)->getUserGroupIds($user_id);
|
2020-11-21 19:53:01 +08:00
|
|
|
|
foreach ($groupIds as $group_id) {
|
2021-05-23 16:52:01 +08:00
|
|
|
|
SocketRoom::getInstance()->addRoomMember(strval($group_id), strval($user_id));
|
2020-11-21 19:53:01 +08:00
|
|
|
|
}
|
2020-11-22 23:10:00 +08:00
|
|
|
|
|
|
|
|
|
if (!$isOnline) {
|
2021-07-20 23:12:18 +08:00
|
|
|
|
event()->dispatch(new TalkEvent(TalkEventConstant::EVENT_ONLINE_STATUS, [
|
2021-07-10 10:55:25 +08:00
|
|
|
|
'user_id' => $user_id,
|
|
|
|
|
'status' => 1,
|
|
|
|
|
]));
|
2020-11-22 23:10:00 +08:00
|
|
|
|
}
|
2020-11-02 22:45:37 +08:00
|
|
|
|
}
|
|
|
|
|
|
2020-11-07 22:57:10 +08:00
|
|
|
|
/**
|
|
|
|
|
* 消息接收回调事件
|
|
|
|
|
*
|
|
|
|
|
* @param Response|Server $server
|
2021-04-20 16:30:57 +08:00
|
|
|
|
* @param Frame $frame
|
2020-11-07 22:57:10 +08:00
|
|
|
|
*/
|
|
|
|
|
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-12-26 21:33:40 +08:00
|
|
|
|
$result = json_decode($frame->data, true);
|
2020-12-02 15:14:29 +08:00
|
|
|
|
|
2021-07-28 23:08:07 +08:00
|
|
|
|
if (!isset(ReceiveHandleService::EVENTS[$result['event']])) {
|
|
|
|
|
return;
|
2021-07-09 19:40:43 +08:00
|
|
|
|
}
|
2021-07-28 23:08:07 +08:00
|
|
|
|
|
|
|
|
|
// 回调处理
|
|
|
|
|
call_user_func_array([$this->receiveHandle, ReceiveHandleService::EVENTS[$result['event']]], [
|
|
|
|
|
$server, $frame, $result['data']
|
|
|
|
|
]);
|
2020-11-02 22:45:37 +08:00
|
|
|
|
}
|
|
|
|
|
|
2020-11-07 22:57:10 +08:00
|
|
|
|
/**
|
|
|
|
|
* 连接创建成功回调事件
|
|
|
|
|
*
|
|
|
|
|
* @param Response|\Swoole\Server $server
|
2021-04-20 16:30:57 +08:00
|
|
|
|
* @param int $fd
|
|
|
|
|
* @param int $reactorId
|
2020-11-07 22:57:10 +08:00
|
|
|
|
*/
|
|
|
|
|
public function onClose($server, int $fd, int $reactorId): void
|
2020-11-02 22:45:37 +08:00
|
|
|
|
{
|
2021-07-09 19:40:43 +08:00
|
|
|
|
$user_id = $this->client->findFdUserId($fd);
|
2020-11-08 22:58:17 +08:00
|
|
|
|
|
2020-11-22 23:31:21 +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
|
|
|
|
|
2021-04-22 16:54:01 +08:00
|
|
|
|
// 删除 fd 绑定关系
|
2021-07-09 19:40:43 +08:00
|
|
|
|
$this->client->unbind($fd);
|
2020-11-08 22:58:17 +08:00
|
|
|
|
|
2020-11-09 17:41:22 +08:00
|
|
|
|
// 判断是否存在异地登录
|
2021-07-09 19:40:43 +08:00
|
|
|
|
$isOnline = $this->client->isOnlineAll($user_id);
|
2021-07-12 22:00:48 +08:00
|
|
|
|
if ($isOnline) return;
|
|
|
|
|
|
2021-07-20 23:12:18 +08:00
|
|
|
|
event()->dispatch(new TalkEvent(TalkEventConstant::EVENT_ONLINE_STATUS, [
|
2021-07-12 22:00:48 +08:00
|
|
|
|
'user_id' => $user_id,
|
|
|
|
|
'status' => 0,
|
|
|
|
|
]));
|
2020-11-02 22:45:37 +08:00
|
|
|
|
}
|
|
|
|
|
}
|