<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                # 安裝服務 ~~~ composer require topthink/think-swoole=2.0.* ~~~ # 創建執行單文件 shurima.php ```php <?php class WebSocketServer { public $server; public $tcp; private $tag = 'swoole_user_sessions'; public function __construct() { $this->clearFds();// 開啟服務前,清除之前建立的fd用戶信息,驗證信息保留 $this->server = new Swoole\WebSocket\Server("0.0.0.0", 9001, SWOOLE_PROCESS, SWOOLE_SOCK_TCP | SWOOLE_SSL); $this->server->set([ //'ssl_cert_file' => '/www/server/panel/vhost/cert/hx.toushizhiku.com/fullchain.pem', //'ssl_key_file' => '/www/server/panel/vhost/cert/hx.toushizhiku.com/privkey.pem', 'ssl_cert_file' => __DIR__.'/config/fullchain.pem', 'ssl_key_file' => __DIR__.'/config/privkey.pem', 'heartbeat_idle_time' => 600,// 表示一個連接如果600秒內未向服務器發送任何數據,此連接將被強制關閉 'heartbeat_check_interval' => 60,// 表示每60秒遍歷一次 'worker_num' => 4, 'max_conn' => 50,// 最大連接數, 'log_file' => __DIR__.'/logs/swoole/log.txt', 'log_level' => 0, 'log_rotation' => SWOOLE_LOG_ROTATION_DAILY ]); $this->tcp = $this->server->listen("0.0.0.0", 9002, SWOOLE_SOCK_TCP); $this->tcp->set([ //'open_http_protocol' => true, ]); $this->server->on('WorkerStart', function ($server, $worker_id){ $redis = new Redis(); $redis->connect('127.0.0.1', 6379); $server->redis = $redis; }); $this->server->on('handshake', function (\Swoole\Http\Request $request, \Swoole\Http\Response $response) { $redis = $this->server->redis; $tag = $this->tag; // websocket握手連接算法驗證 $secWebSocketKey = $request->header['sec-websocket-key']; $patten = '#^[+/0-9A-Za-z]{21}[AQgw]==$#'; if (0 === preg_match($patten, $secWebSocketKey) || 16 !== strlen(base64_decode($secWebSocketKey))) { $response->end(); return false; } echo 'sec-key_'.$request->header['sec-websocket-key']."\n"; // 驗證用戶 $fd = $request->fd; $session_id = $request->cookie['PHPSESSID']; echo 'handshake_'.$fd.'_sess_'.$session_id.'_'.json_encode($request->server['remote_addr'])."\n"; if (!$fd || empty($session_id)) { $response->end(); return false; } if (!$redis->hExists($tag, $session_id)) { $response->end(); return false; } $sess_data = json_decode($redis->hGet($tag, $session_id), true); echo 'handshake_sess_'.json_encode($sess_data).'_time_'.time()."\n"; if (!is_array($sess_data) || !isset($sess_data['user_id']) || !isset($sess_data['create_time'])) { $response->end(); return false; } if ((time() - $sess_data['create_time']) > 86400 || time() < $sess_data['create_time']) { $response->end(); return false; } $sess_data['fd'] = $fd; $redis->hSet($tag, $session_id, json_encode($sess_data)); unset($sess_data, $fd, $session_id, $tag); $key = base64_encode( sha1( $request->header['sec-websocket-key'] . '344EAFA5-E858-257A-95CA-C7AB0DC85B22', true ) ); $headers = [ 'Upgrade' => 'websocket', 'Connection' => 'Upgrade', 'Sec-WebSocket-Accept' => $key, 'Sec-WebSocket-Version' => '13', ]; // WebSocket connection to 'ws://127.0.0.1:9001/' // failed: Error during WebSocket handshake: // Response must not include 'Sec-WebSocket-Protocol' header if not present in request: websocket if (isset($request->header['sec-websocket-protocol'])) { $headers['Sec-WebSocket-Protocol'] = $request->header['sec-websocket-protocol']; } foreach ($headers as $key => $val) { $response->header($key, $val); } // onHandShake 中必須調用 response->status() 設置狀態碼為 101 并調用 response->end() 響應,否則會握手失敗 $response->status(101); $response->end(); }); $this->server->on('message', function (Swoole\WebSocket\Server $server, $frame) { echo "receive from {$frame->fd}:{$frame->data},opcode:{$frame->opcode},fin:{$frame->finish}\n"; $server->push($frame->fd, json_encode(['msg' => 'Hello, welcome.'])); }); $this->tcp->on('receive', function ($server, $fd, $reactor_id, $data) { echo 'receive_'.json_encode($fd).'_'.json_encode($data, 320).'_'.json_encode($reactor_id)."\n"; // 僅遍歷 9001 端口的連接,因為是用的$server,不是$tcp // 獲取tcp連接的信息 $data = json_decode($data, true); if (!empty($data) && isset($data['title']) && isset($data['user_ids'])) { $websocket = $server->ports[0]; $redis = $server->redis; $user_data = $redis->hGetAll($this->tag); $fds = []; $tmp = []; if (is_array($user_data)) { foreach ($user_data as $key => $user) { echo 'receive_user_'.$key.'_'.json_encode($user)."\n"; $tmp = json_decode($user, true); $create_time = !empty($tmp) && is_array($tmp) && isset($tmp['create_time']) ? $tmp['create_time'] : 0; if (!isset($tmp['user_id']) || (time() - $create_time > 86400) || time() < $create_time) { $redis->hDel($this->tag, $key); } if (isset($tmp['fd']) && in_array($tmp['user_id'], $data['user_ids'])) { array_push($fds, $tmp['fd']); } } } foreach ($websocket->connections as $_fd) { if (!in_array($_fd, $fds)) { continue; } if ($server->exist($_fd)) { $server->push($_fd, json_encode(['title' => $data['title']], 320)); } } unset($user_data, $fds, $tmp); // 對端不接收信息直接關閉,不再回復 //$server->send($fd, json_encode(['code' => 200, 'msg' => 'success'])); } else { // 對端不接收信息直接關閉,不再回復 //$server->send($fd, json_encode(['code' => 0, 'msg' => 'params less'])); } }); $this->server->on('close', function ($ser, $fd) { echo "client {$fd} closed\n"; }); $this->server->on('WorkerStop', function ($server, $worker_id){ $server->redis->close(); }); $this->server->start(); } public function clearFds() { $redis = new Redis(); $redis->connect('127.0.0.1', 6379); $tag = $this->tag; if (!$redis->exists($tag)) { $redis->close(); return true; } $datas = $redis->hGetAll($tag); if (is_array($datas)) { foreach ($datas as $key => $data) { $tmp = json_decode($data, true); $create_time = !empty($tmp) && is_array($tmp) && isset($tmp['create_time']) ? $tmp['create_time'] : 0; if (!isset($tmp['user_id']) || (time() - $create_time > 86400) || time() < $create_time) { $redis->hDel($tag, $key); } unset($tmp['fd']); $redis->hSet($tag, $key, json_encode($tmp)); } } $redis->close(); return true; } } new WebSocketServer(); ``` 命令行執行: > php shurima.php # 前端js ~~~ <script> var url = 'wss://aaa.test.com:9001'; var websocket, timer, max = 500, count = 0; var lockConnect = false; var connection = function () { websocket = new WebSocket(url); websocket.onopen = onopen; websocket.onmessage = onmessage; websocket.onclose = onclose; websocket.onerror = onerror; } var onopen = function () { console.log("Connected to WebSocket server."); websocket.send("Hello!"); ping(); } var onmessage = function (evt) { console.log('Retrieved data from server: ' + evt.data); if (evt.data.length) { var msg_data = JSON.parse(evt.data); console.log('message2', msg_data, typeof msg_data) if (msg_data.title == 'undefined' || msg_data.title == null || msg_data.title == '') { console.log('message', msg_data.title) return false; } notifyMsg('光年分配任務', msg_data.title); } ping(); } var onclose = function () { console.log("connection is closed"); reconnection(); } var onerror = function (evt, e) { console.log('Error occured: ' + evt, e); reconnection(); } var pingCheck, pongCheck; var ping = function () { pingCheck && clearTimeout(pingCheck); pongCheck && clearTimeout(pongCheck); pingCheck = setTimeout(function () { websocket.send('ping'); pongCheck = setTimeout(function () { websocket.close(); }, 3500) }, 60000); } var reconnection = function () { // 0 CONNECTING,1 OPEN,2 CLOSING,3 CLOSED if (lockConnect) { return false; } lockConnect = true; count = count + 1; console.log("reconnection " + count + " times and readyState is " + websocket.readyState); timer && clearTimeout(timer); if (count >= max || websocket.readyState == 1) { clearTimeout(timer); count = 0; } else { timer = setTimeout(function () { connection(); lockConnect = false; }, 30000); } } connection(); function notifyMsg(title, content) { var options = { dir: "auto", // 文字方向 body: content, requireInteraction: true, tag: "notification", renotify: true, icon: "https://file.toushivip.com/msg2.png", }; // 先檢查瀏覽器是否支持 if (!window.Notification) { console.log('瀏覽器不支持通知'); } else { console.log('permission', Notification.permission); // 檢查用戶曾經是否同意接受通知 if (Notification.permission === 'granted') { var notification = new Notification(title, options); // 顯示通知 notification.onclick = function (event) { event.preventDefault(); // prevent the browser from focusing the Notification's tab window.open('/portal/distribution'); } } else if (Notification.permission === 'default') { // 用戶還未選擇,可以詢問用戶是否同意發送通知 Notification.requestPermission().then(permission => { if (permission === 'granted') { var notification = new Notification(title, options); // 顯示通知 notification.onclick = function (event) { event.preventDefault(); window.open('/portal/distribution'); } } else if (permission === 'default') { console.warn('用戶關閉授權 未刷新頁面之前 可以再次請求授權'); } else { // denied console.log('用戶拒絕授權 不能顯示通知'); } }); } else { // denied 用戶拒絕 console.log('用戶曾經拒絕顯示通知'); } } } </script> ~~~
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看