• Laravel 中使用 swoole 项目实战开发案例一 (建立 swoole 和前端通信)


    1 开发需要环境

    工欲善其事,必先利其器。在正式开发之前我们检查好需要安装的拓展,不要开发中发现这些问题,打断思路影响我们的开发效率。

    • 安装 swoole 拓展包
    • 安装 redis 拓展包
    • 安装 laravel5.5 版本以上

    如果你还不会用swoole就out了

    2 Laravel 生成命令行

    1. php artisan make:command SwooleDemo
    class SwooleDemo extends Command
    {
    
    protected $signature = 'swoole:demo';
    
    protected $description = '这是关于swoole的一个测试demo';
    
    public function __construct()
    {
        parent::__construct();
    }
    
    public function handle()
    {
        $this->line("hello world");
    }
    }

    我们分别运行 php artisan 指令和 php artisan swoole:demo 会看到关于这个命令的说明,和输出 hello world。(laravel 命令行用法详解)

    3 命令行逻辑代码

    • 编写一个最基础的 swoole 命令行逻辑代码
    <?php
    
    namespace AppConsoleCommands;
    
    use IlluminateConsoleCommand;
    use IlluminateSupportFacadesRedis;
    
    class SwooleDemo extends Command
    {
        // 命令名称
        protected $signature = 'swoole:demo';
        // 命令说明
        protected $description = '这是关于swoole websocket的一个测试demo';
        // swoole websocket服务
        private static $server = null;
    
        public function __construct()
        {
            parent::__construct();
        }
    
        // 入口
        public function handle()
        {
            $this->redis = Redis::connection('websocket');
            $server = self::getWebSocketServer();
            $server->on('open',[$this,'onOpen']);
            $server->on('message', [$this, 'onMessage']);
            $server->on('close', [$this, 'onClose']);
            $server->on('request', [$this, 'onRequest']);
            $this->line("swoole服务启动成功 ...");
            $server->start();
        }
    
        // 获取服务
        public static function getWebSocketServer()
        {
            if (!(self::$server instanceof swoole_websocket_server)) {
                self::setWebSocketServer();
            }
            return self::$server;
        }
        // 服务处始设置
        protected static  function setWebSocketServer():void
        {
            self::$server  = new swoole_websocket_server("0.0.0.0", 9502);
            self::$server->set([
                'worker_num' => 1,
                'heartbeat_check_interval' => 60,    // 60秒检测一次
                'heartbeat_idle_time' => 121,        // 121秒没活动的
            ]);
        }
    
        // 打开swoole websocket服务回调代码
        public function onOpen($server, $request)
        {
            if ($this->checkAccess($server, $request)) {
                self::$server->push($request->fd,"打开swoole服务成功!");
            }
        }
        // 给swoole websocket 发送消息回调代码
        public function onMessage($server, $frame)
        {
    
        }
        // http请求swoole websocket 回调代码
        public function onRequest($request,$response)
        {
    
        }
        // websocket 关闭回调代码
        public function onClose($serv,$fd)
        {
            $this->line("客户端 {$fd} 关闭");
        }
        // 校验客户端连接的合法性,无效的连接不允许连接
        public function checkAccess($server, $request):bool
        {
            $bRes = true;
            if (!isset($request->get) || !isset($request->get['token'])) {
                self::$server->close($request->fd);
                $this->line("接口验证字段不全");
                $bRes = false;
            } else if ($request->get['token'] !== "123456") {
                $this->line("接口验证错误");
                $bRes = false;
            }
            return $bRes;
        }
        // 启动websocket服务
        public function start()
        {
            self::$server->start();
        }
    
    }

    编写 websoket js 代码

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>swoole测试</title>
        <meta name=viewport content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
    </head>
    <body>
    <h1>这是一个测试</h1>
    </body>
    <script>
        var ws;//websocket实例
        var lockReconnect = false;//避免重复连接
        var wsUrl = 'ws://{{$_SERVER["HTTP_HOST"]}}:9502?page=home&token=123456';
    
        function initEventHandle() {
            ws.onclose = function () {
                reconnect(wsUrl);
            };
            ws.onerror = function () {
                reconnect(wsUrl);
            };
            ws.onopen = function () {
                //心跳检测重置
                heartCheck.reset().start();
            };
            ws.onmessage = function (event) {
                //如果获取到消息,心跳检测重置
                //拿到任何消息都说明当前连接是正常的
                var data = JSON.parse(event.data);
                heartCheck.reset().start();
            }
        }
        createWebSocket(wsUrl);
        /**
         * 创建链接
         * @param url
         */
        function createWebSocket(url) {
            try {
                ws = new WebSocket(url);
                initEventHandle();
            } catch (e) {
                reconnect(url);
            }
        }
        function reconnect(url) {
            if(lockReconnect) return;
            lockReconnect = true;
            //没连接上会一直重连,设置延迟避免请求过多
            setTimeout(function () {
                createWebSocket(url);
                lockReconnect = false;
            }, 2000);
        }
        //心跳检测
        var heartCheck = {
            timeout: 60000,//60秒
            timeoutObj: null,
            serverTimeoutObj: null,
            reset: function(){
                clearTimeout(this.timeoutObj);
                clearTimeout(this.serverTimeoutObj);
                return this;
            },
            start: function(){
                var self = this;
                this.timeoutObj = setTimeout(function(){
                    //这里发送一个心跳,后端收到后,返回一个心跳消息,
                    //onmessage拿到返回的心跳就说明连接正常
                    ws.send("heartbeat");
                    self.serverTimeoutObj = setTimeout(function(){//如果超过一定时间还没重置,说明后端主动断开了
                        ws.close();//如果onclose会执行reconnect,我们执行ws.close()就行了.如果直接执行reconnect 会触发onclose导致重连两次
                    }, self.timeout);
                }, this.timeout);
            },
            header:function(url) {
                window.location.href=url
            }
    
        }
    </script>
    </html>
    访问前端页面 (显示如下说明前后端链接成功)

     以上内容希望帮助到大家,很多PHPer在进阶的时候总会遇到一些问题和瓶颈,业务代码写多了没有方向感,不知道该从那里入手去提升,对此我整理了一些资料,包括但不限于:分布式架构、高可扩展、高性能、高并发、服务器性能调优、TP6,laravel,YII2,Redis,Swoole、Swoft、Kafka、Mysql优化、shell脚本、Docker、微服务、Nginx等多个知识点高级进阶干货需要的可以免费分享给大家,需要的可以加入我的官方群点击此处

  • 相关阅读:
    JavaScript基础知识点记录
    CSS基础知识点记录
    HTML基础知识点记录
    学习笔记------jsp基础
    学习笔记-------ultraedit
    【Exception—WebForm】当应用程序不是以 UserInteractive 模式运行时显示模式对话框或窗体是无效操作。请指定 ServiceNotification 或 DefaultDesktopOnly 样式,以显示服务应用程序发出的通知。
    区块链技术基础语言(三十二):Go语言网络编程(下)
    区块链技术基础语言(三十一):Go语言网络编程(上)
    区块链技术基础语言(三十):Go语言常用工具包(下)
    区块链技术语言(二十九)—Go语言常用工具包(上)
  • 原文地址:https://www.cnblogs.com/a609251438/p/12003294.html
Copyright © 2020-2023  润新知