美文网首页
workerman搭建聊天室

workerman搭建聊天室

作者: 张浩宇_ | 来源:发表于2020-06-27 16:37 被阅读0次

    官网手册http://doc.workerman.net/

    在根目录下创建一个index.php

    index.php代码如下: 

    <?php

    use Workerman\Worker;

    require_once __DIR__ . '/Workerman/Autoloader.php';

    use Workerman\Lib\Timer;

    Worker::$daemonize = true;

    // 所有的打印输出全部保存在/stdout.log文件中

    Worker::$stdoutFile = '/stdout.log';

    // 注意:这里与上个例子不同,使用的是websocket协议

    $ws_worker = new Worker("websocket://0.0.0.0:2999");

    // 启动1个进程对外提供服务

    $ws_worker->count = 1;

    // 设置实例的名称

    $ws_worker->name = 'Worker1';

    //定义全局变量

    $user_ip = [];

    // 心跳间隔120秒

    define('HEARTBEAT_TIME', 120);

    // 当收到客户端发来的数据后返回hello $data给客户端

    //闭包使用use传递参数进行使用

    $ws_worker->onMessage = function($connection, $data)use($ws_worker)

    {   

        // 给connection临时设置一个lastMessageTime属性,用来记录上次收到消息的时间

        $connection->lastMessageTime = time();

        global $user_ip;

        file_put_contents('666.txt',$data, FILE_APPEND | LOCK_EX);

        //用户发送的信息内容

        $content = substr($data,mb_strpos($data,':') + 1,mb_strlen($data));

        //用户发送信息的状态请求,比如,登录,发送消息等等

        $sort = strstr($data,':',true);

        //获取用户的ip

        $ip = $connection->getRemoteIp();

        if($sort == 'login'){

            //判断用户昵称是否重复

            $array_search = array_search($content,$user_ip, false);

            if( $array_search != $ip && !empty($array_search)){

                //触发回调,关闭服务器和客户端链接

                $connection->close('sort:'.'401');

            }

            if(!array_key_exists($ip,$user_ip)){

                //记录登录时间

                echo '登录ip:'.$ip.'    登录时间:'.date('Y-m-d H:i:s', time()).'\n';

            }

            // 录入ip和昵称

            $user_ip[$ip] = $content;

            //登录成功,返回200

            $connection->send('sort:'.'200');

        }else if($sort == 'text'){

            //获取用户发送的消息,并返回

            // $connection->send('text:'.$user_ip[$ip].':'.$content);

            //广播,通过$ws_worker->connections获取所有连接服务端的对象,循环给所有在线用户推送信息

            foreach($ws_worker->connections as $connection)

            {

                $connection->send('text:'.$user_ip[$ip].'发送消息:'.$content);

            }

        }else{

            //未知错误,返回500

            $connection->send('sort:'.'500');

        }

    };

    // 进程启动后设置一个每秒运行一次的定时器

    $ws_worker->onWorkerStart = function($ws_worker) {

        Timer::add(1, function()use($ws_worker){

            $time_now = time();

            foreach($ws_worker->connections as $connection) {

                // 有可能该connection还没收到过消息,则lastMessageTime设置为当前时间

                if (empty($connection->lastMessageTime)) {

                    $connection->lastMessageTime = $time_now;

                    continue;

                }

                // 上次通讯时间间隔大于心跳间隔,则认为客户端已经下线,关闭连接,返回402

                if ($time_now - $connection->lastMessageTime > HEARTBEAT_TIME) {

                    $connection->close('sort:'.'402');

                }

            }

        });

    };

    //用户断开连接时触发函数

    $ws_worker->onClose = function($connection)

    {

        global $user_ip;

        //清除用户的ip和用户名

        $ip = $connection->getRemoteIp();

        unset($user_ip[$ip]);

        echo 'ip:'. $ip . '      下线时间:'.date('Y-m-d H:i:s', time()).'\n';

    };

    // 运行worker

    Worker::runAll();

    然后在根目录中的index.html写入以下代码

    <!DOCTYPE html>

    <html lang="en">

    <head>

        <meta charset="UTF-8">

        <title>Title</title>

        <script src="https://libs.baidu.com/jquery/1.8.3/jquery.min.js"></script>

    </head>

    <body>

        <div>你的昵称:<input type="text" id="username" value=""/></div>

        <div>

            回复内容:

            <textarea style="width: 500px;height: 100px" id="content" value=''></textarea>

        </div>

        <div>

            <input type="button" onclick="login()" value="连接服务器">

            <input type="button" onclick="send()" value="发送消息">

            <input type="button" onclick="quit()" value="退出">

        </div>

        <script>

            var socket = null;  //将socket实例保存到变量中

            var isLogin = false;    //登录标识符

            var ws;

            function login(){

                var name = document.getElementById('username').value;

                if(name.length == 0 || name == ''){

                    alert('请输入昵称');

                    return false;

                }

                ws = new WebSocket("ws://www.xxx.com:2999");

                ws.onopen = function() {

                    ws.send('login:'+name);

                    ws.onmessage = function(e) {

                        console.log(e);

                        callback(e);

                    }

                }

            }

            function send(){

                if(!isLogin){

                    alert('请先连接服务器');

                    return false;

                }

                var content =document.getElementById('content').value;

                ws.send('text:' + content);

                ws.onmessage = function(e) {

                    callback(e);

                }

            }

            function quit(){

                if(!isLogin){

                    alert('请先连接服务器');

                }

                ws.send('quit');

                ws.onmessage = function(e){

                    callback(e);

                }

            }

            //返回值处理

            function callback(e){

                //返回的状态

                var sort = e.data.substring(0,e.data.indexOf(':'));

                //返回的内容

                var content = e.data.substring(e.data.indexOf(':')+1);

                if(sort == 'text'){

                    alert(content);

                }else if(sort == 'sort'){

                    if(content == 401){

                        alert('用户名重复,连接失败');

                    }else if(content == 200){

                        isLogin = true;

                        alert('连接成功');

                    }else if(content == 402){

                        isLogin = false;

                        alert('长时间未发消息,已断开连接,请重新连接服务器');

                    }else if(content == 202){

                        isLogin = false;

                        alert('成功断开连接');

                    }else if(content == 500){

                        alert('未知错误');

                    }else{

                        alert('未知错误');

                    }

                }else{

                    alert('连接失败');

                }

            }

        </script>

    </body>

    </html>

    弄好了之后,打开终端,cd 至网站根目录,执行index.php脚本,监听端口,并加入守护进程

    php index.php start -d

    执行成功,那么你的一个简单的即时通讯功能就完成了

    测试:两个不同的用户登录网页,输入昵称,连接服务器,其中一个发送消息,另一个在页面中有收到

    那么恭喜你,一个简单的即时通讯功能就这样做出来了

    相关文章

      网友评论

          本文标题:workerman搭建聊天室

          本文链接:https://www.haomeiwen.com/subject/eekvfktx.html