workerman搭建聊天室

首先,先打开官网手册   http://doc.workerman.net/

根据手册里安装里的提示,完成环境检测,和安装对应的扩展,并把对应的WorkerMan代码包下载解压至根目录

在根目录下创建一个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

 

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

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

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

 

 

参考文章:https://blog.csdn.net/qq_33862644/article/details/79554321

 

posted @ 2020-03-13 11:56  钧一  阅读(1193)  评论(0编辑  收藏  举报