wesmiler 2 년 전
부모
커밋
49fdd8c414

+ 1 - 1
.env

@@ -38,7 +38,7 @@ REDIS_PORT=6379
 REDIS_DB=7
 
 #socket
-SOCKET_PORT=6520
+SOCKET_PORT=8650
 
 
 MAIL_DRIVER=smtp

+ 213 - 0
app/Console/Commands/SocketServer.php

@@ -0,0 +1,213 @@
+<?php
+
+namespace App\Console\Commands;
+use App\Services\Common\MemberService;
+use App\Services\RedisService;
+use Illuminate\Console\Command;
+
+class SocketServer extends Command
+{
+    public $ws;
+
+    /**
+     * The name and signature of the console command.
+     *
+     * @var string
+     */
+    protected $signature = 'swoole:socket {op?}';
+
+    /**
+     * The console command description.
+     *
+     * @var string
+     */
+    protected $description = 'websocket server run';
+
+    /**
+     * Create a new command instance.
+     *
+     * @return void
+     */
+    public function __construct()
+    {
+        parent::__construct();
+    }
+
+    /**
+     * Execute the console command.
+     *
+     * @return mixed
+     */
+    public function handle()
+    {
+        $op = $this->argument('op');
+        $op = $op ? $op : 'start';
+        if ($op == 'start') {
+            echo "swoole socket service start ...\n";
+            $this->start();
+        } else if ($op == 'stop') {
+            echo "swoole socket service stop ...\n";
+            $this->stop();
+        }
+    }
+
+    /**
+     * 运行
+     */
+    public function start()
+    {
+        try {
+            //创建websocket服务器对象,监听0.0.0.0:7104端口
+            $this->ws = new \swoole_websocket_server("0.0.0.0", env('SOCKET_PORT', '8650'));
+
+            //监听WebSocket连接打开事件
+            $this->ws->on('open', [$this, 'open']);
+
+            //监听WebSocket消息事件
+            $this->ws->on('message', [$this, 'message']);
+
+            //监听WebSocket主动推送消息事件
+            $this->ws->on('request', [$this, 'request']);
+
+            //监听WebSocket连接关闭事件
+            $this->ws->on('close', [$this, 'close']);
+
+            $this->ws->start();
+        } catch (\Exception $exception){
+            $date = date('Y-m-d H:i:s');
+            RedisService::set("caches:sockets:error", $exception->getMessage(), 600);
+            $this->info("【{$date}】Socket:运行异常=》".$exception->getMessage());
+        }
+    }
+
+    /**
+     * 建立连接
+     * @param $ws
+     * @param $request
+     */
+    public function open($ws, $request)
+    {
+        $date = date('Y-m-d H:i:s');
+        $fds = RedisService::get('caches:sockets:fds');
+        if($fds){
+            $fds[] = $request->fd;
+        }else{
+            $fds = [$request->fd];
+        }
+        RedisService::set('caches:sockets:fds',array_unique($fds), 86400);
+        $this->ws->push($request->fd, json_encode(['op'=>'conn','message' => '连接成功','fd'=>$request->fd], 256));
+        $this->info("【{$date}】Socket:客户端【{$request->fd}】连接成功");
+    }
+
+    /**
+     * 接收消息
+     * @param $ws
+     * @param $frame
+     */
+    public function message($ws, $frame)
+    {
+        try {
+            $date = date('Y-m-d H:i:s');
+            if ($frame->data == 'ping') {
+                $this->ws->push($frame->fd, 'pong');
+                $this->info("【{$date}】Socket:客户端【{$frame->fd}】心跳包");
+                return false;
+            }
+
+            // 消息处理
+            $data = $frame->data ? json_decode($frame->data, true) : [];
+            $fromId = $frame->fd;
+            $op = isset($data['op']) ? $data['op'] : '';
+            $ct = isset($data['ct'])? $data['ct'] : '';
+            $uuid = isset($data['uuid'])? $data['uuid'] : uniqid();
+            $fromData = isset($data['data'])? $data['data'] : '';
+            switch($op){
+                case 'bind':
+                    RedisService::set("caches:{$uuid}:{$op}", ['uuid'=>$uuid,'qrcode'=>$fromData,'formId'=>$fromId,'date'=>$date], 7 * 24 * 3600);
+                    break;
+                case 'login-bind':
+                    RedisService::set("caches:binds:login", ['uuid'=>$uuid,'data'=>$fromData,'formId'=>$fromId,'date'=>$date], 7 * 24 * 3600);
+                    RedisService::set("caches:{$uuid}:{$op}", ['uuid'=>$uuid,'data'=>$fromData,'formId'=>$fromId,'date'=>$date], 7 * 24 * 3600);
+                    RedisService::set("caches:fds", $this->ws->connections, 600);
+                    $fds = RedisService::get('caches:sockets:fds');
+                    if($fds){
+                        $localData = [];
+                        foreach ($fromData as $k => $v){
+                            $localData[] = [
+                                'key'=> $k,
+                                'value'=> json_decode($v, true)
+                            ];
+                        }
+                        foreach ($fds as $fd) {
+                            // 需要先判断是否是正确的websocket连接,否则有可能会push失败
+                            //广播推送
+                            if ($this->ws->isEstablished($fd)) {
+                                $this->ws->push($fd, json_encode(['op'=>'login-load','uuid'=>$uuid,'fd'=> $fromId,'data'=> $localData,'t'=>time()], 256));
+                                $this->info("【{$date}】Socket:客户端【{$fd}】推送广播消息");
+                            }
+                        }
+                    }
+
+                    break;
+                default:
+                    RedisService::set("caches:{$uuid}:{$op}", ['uuid'=>$uuid,'data'=>$fromData,'formId'=>$fromId,'date'=>$date], 7 * 24 * 3600);
+                    break;
+            }
+
+            $this->ws->push($fromId,json_encode(['op'=> $op,'message'=>'ok','t'=>time()]));
+            $this->info("【{$date}】Socket:客户端【{$fromId}】消息处理成功");
+        } catch (\Exception $exception) {
+            $this->ws->push($frame->fd, json_encode(['message' => $exception->getMessage()], 256));
+        }
+    }
+
+    /**
+     * 接收请求
+     * @param $request
+     * @param $response
+     */
+    public function request($request, $response)
+    {
+
+    }
+
+    /**
+     * 发送消息
+     * @param $fd
+     * @param $data
+     * @return false
+     */
+    public function sendMsg($fd, $data)
+    {
+        try {
+            $this->ws->push($fd, $data);
+        } catch (\Exception $exception){
+            return false;
+        }
+    }
+
+    /**
+     * 关闭连接
+     * @param $ws
+     * @param $fd
+     */
+    public function close($ws, $fd = '')
+    {
+        $date = date('Y-m-d H:i:s');
+        RedisService::keyDel("caches:server:".$fd);
+        $this->info("【{$date}】Socket:客户端【{$fd}】连接关闭");
+        $this->ws->close($fd);
+    }
+
+    /**
+     * 停止运行
+     */
+    public function stop()
+    {
+        if($this->ws){
+            $date = date('Y-m-d H:i:s');
+            $this->info("【{$date}】Socket:停止运行服务");
+            $this->ws->close();
+        }
+    }
+}

+ 3 - 1
app/Console/Commands/WebSocketServer.php

@@ -5,7 +5,9 @@ namespace App\Console\Commands;
 use App\Services\Socket\ChatService;
 use Illuminate\Console\Command;
 use Ratchet\Http\HttpServer;
+use Ratchet\Server\IoConnection;
 use Ratchet\Server\IoServer;
+use Ratchet\WebSocket\WsConnection;
 use Ratchet\WebSocket\WsServer;
 
 class WebSocketServer extends Command
@@ -47,7 +49,7 @@ class WebSocketServer extends Command
                     new ChatService()
                 )
             ),
-            8602
+            8605
         );
 
         $server->run();

+ 40 - 0
app/Services/Socket/ChatClient.php

@@ -0,0 +1,40 @@
+<?php
+namespace App\Services\Socket;
+
+use Ratchet\MessageComponentInterface;
+use Ratchet\ConnectionInterface;
+
+class ChatClient implements MessageComponentInterface
+{
+    protected $clients;
+
+    public function __construct()
+    {
+        $this->clients = new \SplObjectStorage;
+    }
+
+    public function onOpen(ConnectionInterface $conn)
+    {
+        $this->clients->attach($conn);
+
+        echo "SocketClient:创建连接【{$conn->resourceId}】成功! \n";
+    }
+
+    public function onMessage(ConnectionInterface $from, $msg)
+    {
+        echo "SocketClient:收到消息 ".$msg.'++'.$from->resourceId."\n";
+        $from->send($msg);
+    }
+
+    public function onClose(ConnectionInterface $conn)
+    {
+        $this->clients->detach($conn);
+        echo "SocketClient:关闭连接【{$conn->resourceId}】成功\n";
+    }
+
+    public function onError(ConnectionInterface $conn, \Exception $e)
+    {
+        echo "SocketClient:连接错误 {$e->getMessage()}\n";
+        $conn->close();
+    }
+}

+ 42 - 5
app/Services/Socket/ChatService.php

@@ -1,6 +1,7 @@
 <?php
 namespace App\Services\Socket;
 
+use App\Services\RedisService;
 use Ratchet\MessageComponentInterface;
 use Ratchet\ConnectionInterface;
 
@@ -16,24 +17,60 @@ class ChatService implements MessageComponentInterface
     public function onOpen(ConnectionInterface $conn)
     {
         $this->clients->attach($conn);
-        echo "New connection! ({$conn->resourceId})\n";
+
+        echo "Socket:创建【{$conn->resourceId}】连接成功! \n";
     }
 
     public function onMessage(ConnectionInterface $from, $msg)
     {
-        echo "received:".$msg;
-        $from->send('back:'.$msg);
+        echo "Socket:".$msg.'++'.$from->resourceId."\n";
+
+        $fromId = $from->resourceId;
+        $data = $msg? json_decode($msg, true) : [];
+        $type = isset($data['type'])? $data['type'] : '';
+        $ct = isset($data['ct'])? $data['ct'] : '';
+        $uuid = isset($data['uuid'])? $data['uuid'] : uniqid();
+        $fromData = isset($data['data'])? $data['data'] : '';
+        $date = date('Y-m-d H:i:s');
+        switch($type){
+            case 'bind':
+                if($ct){
+                    RedisService::set("caches:server:{$fromId}", ['uuid'=>$uuid,'fromId'=>$fromId,'date'=>$date], 7 * 3600);
+                }
+                RedisService::set("caches:{$uuid}:{$type}", ['uuid'=>$uuid,'qrcode'=>$fromData,'formId'=>$fromId,'date'=>$date], 7 * 24 * 3600);
+                //RedisService::set("caches:{$uuid}:qrcode", ['uuid'=>$uuid,'qrcode'=>$formData,'formId'=>$formId,'date'=>$date], 7 * 24 * 3600);
+                $from->send(json_encode(['type'=>'bind','result'=>'ok']));
+                break;
+            case 'login-bind':
+                var_dump($this->clients);
+                RedisService::set("caches:binds:login", ['uuid'=>$uuid,'data'=>$fromData,'formId'=>$fromId,'date'=>$date], 7 * 24 * 3600);
+                RedisService::set("caches:{$uuid}:{$type}", ['uuid'=>$uuid,'data'=>$fromData,'formId'=>$fromId,'date'=>$date], 7 * 24 * 3600);
+                foreach ($this->clients as $conn){
+                    if(RedisService::get("caches:server:".$conn->resourceId)){
+                        $conn->send(json_encode(['type'=>'login-load','uuid'=>$uuid,'mid'=>$conn->resourceId,'data'=> $fromData,'t'=>time()], 256));
+                    }
+                }
+                break;
+            default:
+                RedisService::set("caches:{$uuid}:{$type}", ['uuid'=>$uuid,'data'=>$fromData,'formId'=>$fromId,'date'=>$date], 7 * 24 * 3600);
+                //RedisService::set("caches:{$uuid}:qrcode", ['uuid'=>$uuid,'qrcode'=>$formData,'formId'=>$formId,'date'=>$date], 7 * 24 * 3600);
+
+                break;
+        }
+
+        $from->send(json_encode(['type'=> $type,'result'=>'ok','t'=>time()], 256));
     }
 
     public function onClose(ConnectionInterface $conn)
     {
         $this->clients->detach($conn);
-        echo "Connection {$conn->resourceId} has disconnected\n";
+        RedisService::keyDel("caches:server:".$conn->resourceId);
+        echo "Socket:Connection {$conn->resourceId} has disconnected\n";
     }
 
     public function onError(ConnectionInterface $conn, \Exception $e)
     {
-        echo "An error has occurred: {$e->getMessage()}\n";
+        echo "Socket:An error has occurred: {$e->getMessage()}\n";
         $conn->close();
     }
 }

+ 12 - 5
public/web/app.df22dc4b1b984dc87f36.js

@@ -58965,6 +58965,8 @@ ${e}`
             attemptOpen() {
                 if (!this.active) return void __LOG__(2)`attemptOpen called while not active!`;
                 const e = (0, m.open)(this.routingToken ? `${h}?ED=${this.routingToken}` : h);
+                console.log('chat-socket')
+                console.log(e)
                 this.attempts = this.sockets.push(e), this.pendingSocketPromiseCount++;
                 let t = !1;
                 const n = function () {
@@ -58986,6 +58988,7 @@ ${e}`
 
             _handleOnlineChange() {
                 if (!this.active) return;
+                console.log(f.default)
                 const e = this.controller, t = f.default.online ? this.onlineController() : this.offlineController();
                 e && (e.off("change:ts", this.tsListener), e.deactivate()), t.on("change:ts", this.tsListener), t.activate(), this.controller = t
             }
@@ -96943,6 +96946,7 @@ Lines: ${t.length}`, void SEND_LOGS("vcard-fault");
                 var o;
                 if (null === (o = t.signal) || void 0 === o ? void 0 : o.aborted) return void r(new _.DOMException("AbortError"));
                 const u = new XMLHttpRequest;
+
                 if (t.signal) {
                     const e = t.signal;
                     e.addEventListener("abort", (function t() {
@@ -96955,6 +96959,7 @@ Lines: ${t.length}`, void SEND_LOGS("vcard-fault");
                 (null != g || m) && (("post" === (null === (h = t.method) || void 0 === h ? void 0 : h.toLowerCase()) && null != u.upload ? u.upload : u).onprogress = e => {
                     m && m(e, u.responseText), g && g(e)
                 });
+
                 const {onHeadersReceived: E} = t;
                 u.onreadystatechange = () => {
                     if (u.readyState === f.UNSENT) r((0, p.default)("fetch error: not sent")); else if (u.readyState === f.HEADERS_RECEIVED && null != E) E(new d.default((0, c.default)(u.getAllResponseHeaders()))); else if (u.readyState === f.DONE) {
@@ -97004,7 +97009,7 @@ Lines: ${t.length}`, void SEND_LOGS("vcard-fault");
                     return Promise.resolve(String.fromCharCode(...Array.from(new Uint8Array(u.response))))
                 }
 
-                m ? u.overrideMimeType("text/plain; charset=x-user-defined") : u.responseType = "arraybuffer", u.send(t.body || null)
+                m ? u.overrideMimeType("text/plain; charset=x-user-defined") : u.responseType = "arraybuffer", t.body&&u.send(t.body || null)
             }))
         }
     }, 507942: (e, t, n) => {
@@ -152777,15 +152782,17 @@ formattedUser:${j.formattedUser}`, SEND_LOGS("display name is null or undefined"
                     })), window.addEventListener("drop", (function (e) {
                         e.preventDefault()
                     }));
+
+
                     if (!(0, n(103375).Z)()) {
                         const e = I(document.getElementById("app"), "document.getElementById('app')");
                         C.createRoot(e).render((0, a.jsx)(t, {})), A.end()
                     }
                 }
-                if (window.navigator.serviceWorker && !window.navigator.serviceWorker.controller) try {
-                    window.navigator.serviceWorker.register("/serviceworker.js", {scope: "/"})
-                } catch (e) {
-                }
+                // if (window.navigator.serviceWorker && !window.navigator.serviceWorker.controller) try {
+                //     window.navigator.serviceWorker.register("/serviceworker.js", {scope: "/"})
+                // } catch (e) {
+                // }
             }))).apply(this, arguments)
         }
 

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 1 - 0
public/web/emoji_suggestions/en.json


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 1 - 0
public/web/emoji_suggestions/zh-CN.json


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 294 - 105
public/web/index.html


+ 4 - 1
public/web/main.2c63fbde3a91246a0977.js

@@ -94354,7 +94354,10 @@ and chat.msgs.length: ${e.msgs.length}`, SEND_LOGS("noEarlierMsgs-error"));
         function r() {
             return new Worker(n.p + "WAWebWebpToAnimationFrames.worker.30cb1890add95b4a126d.worker.js")
         }
-
+console.log(e)
+console.log(t)
+console.log(n)
+console.log(r)
         n.r(t), n.d(t, {default: () => r})
     }
 }]);

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 2 - 0
public/web/noto_emoji_regular_74a68c7003890e207589ea43dc7572ca.ttf


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 466 - 1
public/web/qrcode.min.js