123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348 |
- <?php
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- namespace app\common\websocket;
-
-
- use app\common\enum\ChatMsgEnum;
- use app\common\utils\Redis;
- use Swoole\Server;
- use Swoole\Websocket\Frame;
- use think\App;
- use think\Event;
- use think\Request;
- use think\swoole\Websocket;
- use think\swoole\websocket\Room;
-
- class Handler extends Websocket
- {
- protected $server;
-
- protected $room;
-
- protected $parser;
-
- protected $cache;
-
- protected $prefix;
-
- public function __construct(App $app, Server $server, Room $room, Event $event, Parser $parser, Redis $redis)
- {
- $this->server = $server;
- $this->room = $room;
- $this->parser = $parser;
- $this->cache = $redis;
- $this->prefix = config('default.websocket_prefix');
- parent::__construct($app, $server, $room, $event);
- }
-
-
-
-
- public function onOpen($fd, Request $request)
- {
- $token = $request->get('token/s');
- $type = $request->get('type/s');
- $client = $request->get('client/d');
- $shop_id = $request->get('shop_id/d', 0);
-
- try {
- $user = $this->triggerEvent('login', ['client' => $client, 'token' => $token, 'type' => $type]);
-
- if ($user['code'] == 20001 || empty($user['data']['id'])) {
- throw new \Exception(empty($user['msg']) ? "未知错误" : $user['msg']);
- }
- } catch (\Throwable $e) {
- echo 'onOpen错误:' . $e->getMessage();
- return $this->server->close($fd);
- }
-
-
- $this->bindFd($type, $user['data'], $fd, $shop_id);
-
- $this->ping($fd);
-
- return $this->pushData($fd, 'login', [
- 'msg' => '连接成功',
- 'msg_type' => ChatMsgEnum::TYPE_TEXT
- ]);
- }
-
-
-
-
- public function onMessage(Frame $frame)
- {
- $param = $this->parser->decode($frame->data);
-
- try {
-
- if ('ping' === $param['event']) {
- return $this->ping($frame->fd);
- }
-
- $param['handle'] = $this;
- $param['fd'] = $frame->fd;
-
- return $this->triggerEvent($param['event'], $param);
-
- } catch (\Throwable $e) {
- echo $e->getMessage();
- return $this->pushData($frame->fd, 'error', [
- 'msg' => $e->getMessage(),
- 'msg_type' => ChatMsgEnum::TYPE_TEXT
- ]);
- }
- }
-
-
-
-
-
- public function onClose($fd, $reactorId)
- {
- $this->triggerEvent('close', ['handle' => $this, 'fd' => $fd]);
- $this->removeBind($fd);
- $this->server->close($fd);
- }
-
-
-
-
- public function triggerEvent(string $event, array $data)
- {
- return $this->event->until('swoole.websocket.' . $event, $data);
- }
-
-
-
-
-
- public function bindFd($type, $user, $fd, $shop_id)
- {
- $uid = $user['id'];
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- $fdKey = $this->prefix . 'fd_' . $fd;
- $fdData = [
- 'uid' => $uid,
- 'type' => $type,
- 'nickname' => $user['nickname'],
- 'avatar' => $user['avatar'],
- 'client' => $user['client'],
- 'shop_id' => $shop_id
- ];
- $this->cache->set($fdKey, json_encode($fdData, true));
-
-
-
- $uidKey = $this->prefix . $type . '_' . $uid;
- $this->cache->sadd($uidKey, $fd);
-
-
- if ($type == 'kefu') {
- $groupKey = $this->prefix . 'shop_' . $shop_id . '_kefu';
- } else {
- $groupKey = $this->prefix . 'user';
- }
- $this->cache->sadd($groupKey, $uid);
- }
-
-
-
-
- public function removeBind($fd)
- {
- $data = $this->getDataByFd($fd);
- if ($data) {
- $key = $this->prefix . 'user';
- if($data['type'] == 'kefu') {
- $key = $this->prefix . 'shop_'. $data['shop_id'] . '_kefu';
- }
- $this->cache->srem($key, $data['uid']);
- $this->cache->srem($this->prefix . $data['type'] . '_' . $data['uid'], $fd);
- }
- $this->cache->del($this->prefix . 'fd_' . $fd);
- }
-
-
-
-
-
- public function getFdByUid($uid, $type)
- {
- $key = $this->prefix . $type . '_' . $uid;
- return $this->cache->sMembers($key);
- }
-
-
-
-
-
- public function getDataByFd($fd)
- {
- $key = $this->prefix . 'fd_' . $fd;
- $result = $this->cache->get($key);
- if (!empty($result)) {
- $result = json_decode($result, true);
- }
- return $result;
- }
-
-
-
-
- public function ping($fd)
- {
- $data = $this->getDataByFd($fd);
- if (!empty($data)) {
- return $this->pushData($fd, 'ping', ['client_time' => time()]);
- }
- return true;
- }
-
-
-
-
-
-
- public function pushData($fd, $event, $data)
- {
- $data = $this->parser->encode($event, $data);
-
-
- if (!is_array($fd)) {
- $fd = [$fd];
- }
-
-
- foreach ($fd as $item) {
- if ($this->server->exist($item)) {
- $this->server->push($item, $data);
- }
- }
- return true;
- }
-
-
-
-
-
- public function onlineFd($fd)
- {
- $result = [];
-
- if (empty($fd)) {
- return $result;
- }
-
- if (!is_array($fd)) {
- $fd = [$fd];
- }
-
- foreach ($fd as $item) {
-
-
-
-
-
-
-
- if ($this->server->exist($item)) {
- $result[] = $item;
- }
- }
-
- return $result;
- }
-
- }
|