美文网首页
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