嘿,你忘记写博客了~

盛年不重来,一日难再晨,及时宜自勉,岁月不待人....

YII2+swoole实现聊天室

发布时间:2020-12-03编辑:windydeng浏览(808)评论览(0)

    本文讲解的是在YII2配合swoole的前提下实现的一对一聊天,swoole可在服务器自行安装,安装教程链接:https://blog.csdn.net/gaokcl/article/details/91357622,安装过程需要注意的点如下:

            1.编译安装

                    ./configure配置PHP的文件路径要配对,不然会安装出错 例如:--with=php-config = /usr/local/php/bin/php-config

           2.配置扩展

                这里需要注意的是,php.ini文件增加swoole扩展,必要时加上绝对路径


    其次讲下YII2,我是用的高级版,有前后台之分,目前的聊天室也是主要给线上项目www.phpfire.online

    开发增加功能,好了,该步入正题了:

            先看下我目前实现了界面效果,主要有,切换用户聊天,发送信息,消息接受者可实时接收消息同步


        BD6AD12A-7651-4629-9B8F-0EF690D9F7A0.png

                好了,首先贴下我服务器的代码,在YII2中,一般脚本执行文件都是在./commands下面创建控制器,我这是属于高级版,所以是放在了./console/controller里面,swoole服务器也是得在命令行cli模式下运行,具体如何运行如下:

                D8843CE7-34E4-4a81-97CD-9FE4A2F1C72F.png

                    75219116-1D2B-4da8-B419-BE67700B9EFF.png

                这里需要有一个注意项,你此时运行程序,当此次终端关闭将会断开连接,如果你不想被终端,那么需要使用特定的运行命令来让这个进程一直运行下去,我目前是选择了使用nohup,nohup命令是永久执行,忽略挂起信号。&是指在后台运行。所以我运行linux程序的命令变成了这样:mohup ./yii swoole-chat/run &

                接下来贴下我的swoole核心代码代码:

            

      public function actionRun(){

            $this->serv = new \swoole_websocket_server("0.0.0.0", 8090);

            $this->serv->set(array(

                'worker_num' => 8,

                'daemonize' => false,

                'max_request' => 10000,

                'dispatch_mode' => 2,

                'debug_mode' => 1

            ));


            $this->serv->on('Open', array($this, 'onOpen'));

            $this->serv->on('Message', array($this, 'onMessage'));

            $this->serv->on('Close', array($this, 'onClose'));


            $this->serv->start();


        }

                这段代码需要注意点的就是socket的连接了,有些朋友会发现连接不上socket,反斜杠需要,我采用8090这个端口作为swoole监听端口,需要去你的服务器安全组开放,这个方法保证,连接监听关闭三个操作的正常。


            前端代码websockt的连接代码如下:

            

    <script>   
     var socket = new WebSocket('ws://192.168.122.128:8090');    // 打开Socket  这里的IP和端口填写你自己的
        socket.onopen = function(event) {
            console.log(event);
        };
        socket.onmessage=function(event){     
     
            console.log(event);
              
        }
        function sendMessage(touser){   
              
            socket.send(msg);
        }
        </script>

            上面一段代码就是websockt的最基本的连接监听关闭了,注意上面WebSocket里面的IP地址和端口号要填写正确,不然会连接不上,其次就是每次连接,都会在服务器onopen产生连接数据,此时可以推送到前端展示一些初始化信息。但此时注意,此次服务器onopen方法推送的数据都是在前端onmessage方法接受,我这里是一对一聊天,所以在建立连接的时候,就需要初始化双方的聊天记录,例如有两个用户a和b,必须把用户a的uid和用户带着参数传递到swoole后台onopen方法去接受,我此时连接的websockt是这样的:

    new WebSocket('ws://192.168.122.128:8090?uid=' + send_id + '&to_id=' + this.to_id);

            让后台接受用户a的uid和用户b的uid之后,执行db操作查询历史记录,然后通过swoole后台的push操作推送给用户,push注意事项,两个参数,第一个,fd,第二个,push的数据

    $ws->push($request->fd, "hello, welcome\n");//例如这样

        这里有几个需要注意的点,fd是什么?简单来说,每次用户建立起一个socket进程之后,都会给这个进程

    分配一个fd作为当前连接的唯一标识,当断开连接重新连接,fd会变化。其次就是推送的数据,我们需要把

    推送的数据转换为字符串形式推送到前端:

        

    $this->serv->push($fd, json_encode($chatData));

        诸如上面就是我其中推送的代码,前端用JSON.parse去接受,将字符串转换为json对象

       

        说到fd,在构建数据库表的设计中,我们需要创建一个fd绑定表,一个聊天记录表,fd绑定表用来绑定

     用户uid和fd设计如下截图:

        

    500EC4E3-14CD-4266-B999-63136A86020F.png

        好了,不多哔哔,我们就此走通了websockt的连接和初始化历史消息,接下来讲发送消息,

    socket.send(JSON.stringify(pData)); //这个前端就是发送消息的方法,注意需要转化为字符串传递

    swoole后台接受的话,会自动在onMessage方法里面触发接受,

    onMessage($server, $frame)//前端推送的数据就在$frame指向的data里面,$frame还包含了此次socket的fd

    在这里注意,我每次发送消息进入onMessage方法都要注意当前传递的fd和数据库uid绑定的fd是否一致,否则需要更新fd,这里经过数据过滤,把返回信息推送给用户a和b,此时需要推送给两个用户,那么需要推送两次,通过查询数据库的fd去推送,至于其它的具体操作就不多讲了,本文讲的是一些细节问题,和注意事项,具体要实现一个真正的聊天,还需要写很多的代码,如果你有思考过各种场合的处理,就会发现还有很多代码需要开发。下面附一下我的主要代码,一些YII2的操作就不贴了:


    SwooleChatControllers.txt

    swoole_chat(前端).txt


关键字词:YII2+swoole实现聊天室