启动workman php think worker:server 加上-d 后台运行

1、tp6安装workerman扩展

	composer require topthink/think-worker

2、在config/worker_server.php下面配置worker_class(注意:反斜杠不能写错)
在这里插入图片描述
3、app目录下创建http应用并创建worker文件
![在这里插入图片描述](https://img-blog.csdnimg.cn/2d3de829958941c5bab3d907340e1b4e.png在这里插入图片描述

Worker.php源代码

<?php
declare (strict_types = 1);

namespace app\http;

use think\facade\Db;
use think\worker\Server;
use Workerman\Lib\Timer;

// define('HEARTBEAT_TIME', 30);// 心跳间隔
class Worker extends Server
{
	protected $socket = 'websocket://0.0.0.0:2345';
	
	protected static $heartbeat_time = 50;
	
	public function onWorkerStart($worker)
	{
		Timer::add(10, function()use($worker){
			$time_now = time();
			#这里统计下线人员的id
			$offline_user = [];
			
			foreach($worker->connections as $connection) {
				// 有可能该connection还没收到过消息,则lastMessageTime设置为当前时间
				if (empty($connection->lastMessageTime)) {
					$connection->lastMessageTime = $time_now;
					continue;
				}
				// 上次通讯时间间隔大于心跳间隔,则认为客户端已经下线,关闭连接
				// if ($time_now - $connection->lastMessageTime > HEARTBEAT_TIME) {
				if ($time_now - $connection->lastMessageTime > self::$heartbeat_time) {
					#这里统计下线人员的id
					$offline_user[] = $connection->uid;
					#关闭连接
					$connection->close();
				}
				
				#这里是一个用户下线后通知其他用户
				if (count($offline_user) > 0){
					$msg = ['type'=>'message','uid'=>$connection->uid,"message"=>"用户【".implode(',',$offline_user)."】下线了"];
					$connection->send(json_encode($msg));
				}
			}
		});
	}
	
	public function onMessage($connection,$data)
	{
		#最后接收消息时间
		$connection->lastMessageTime = time();
		
		
		$msg_data = json_decode($data,true);
		if (!$msg_data){
			return;
		}
		#绑定用户ID
		if ($msg_data['type'] == 'bind' && !isset($connection->uid)){
			$connection->uid = $msg_data['uid'];
			$this->worker->uidConnections[$connection->uid] = $connection;
		}
		
		
		// Db::name('online_customer_service')->insert();
		
		#单人发消息
		if ($msg_data['type'] == 'text' && $msg_data['mode'] == 'single'){
			if (isset($this->worker->uidConnections[$msg_data['to_id']])){
				$conn = $this->worker->uidConnections[$msg_data['to_id']];
				$conn->send($data);
			}
		}
		#群聊
		if ($msg_data['type'] == 'text' && $msg_data['mode'] == 'group'){
			#实际项目通过群号查询群里有哪些用户
			$group_user = [10009,10010,10011,10012,10013,10014,10015,10016,10017];
			foreach ($group_user as $key => $val){
				if (isset($this->worker->uidConnections[$val])){
					$conn = $this->worker->uidConnections[$val];
					$conn->send($data);
				}
			}
			
		}
		
		// #向所有用户发送消息
		// foreach ($this->worker->connections as $key => $con){
		// 	$con->send($data);
		// }
		
		// $connection->send(json_encode($data));
		// $connection->send($data);
	}
	
	
}

4、在app/http/view创建index.html文件

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <title></title>
    <link rel="stylesheet" type="text/css" href="/static/httpchat/font_Icon/iconfont.css">

    <script src="/static/admin/jquery/jquery-3.6.0.min.js"></script>
    <style>
        .userlist li{
            background: rgb(0 0 0 / 5%);
            text-align: left;
            padding: 5px;
            height: 49px;
            /*line-height: 30px;*/
            font-size: 16px;
            border-bottom: 1px solid rgb(0 0 0 / 5%);
        }
        .userlist li img {
            width: 40px;
            height: 40px;
            padding-right: 5px;
        }
        .message-num{
            right: 2px;
        }

        .ChatInfoName{
            height: 50px;
            border-bottom: 1px solid #D9D9D9;
            line-height: 50px;
            font-size: 16px;
            padding: 0 10px;
        }
        .chatBox-content{
            height: 498px !important;
            width: 100%;
        }
        .chatBox-content-demo{
            width: 100%;
            height: 370px !important;
            overflow-y: scroll;
        }
        .div-textarea{
            width: 490px !important;
            /*min-height: 20px;*/
            height: 100px;
            _height: 120px;
            padding: 3px;
            outline: 0;
            background: #fff;
            font-size: 14px;
            line-height: 20px;
            word-wrap: break-word;
            overflow-x: hidden;
            overflow-y: auto;
            user-modify: read-write-plaintext-only;    /*纯文本*/
            -webkit-user-modify: read-write-plaintext-only;
            -moz-user-modify: read-write-plaintext-only;
        }
        .div-textarea:focus{
            box-shadow: 0 0 15px rgba(82, 168, 236, 0.6);
        }

        .clearfloat:after{
            display:block;
            clear:both;
            content:"";
            visibility:hidden;
            height:0
        }
        .clearfloat{
            zoom:1;
            margin: 10px 10px;
        }
        .clearfloat .right{
            float: right;
        }
        .author-name{
            text-align: center;
            margin: 15px 0 5px 0;
            color: #888;
        }

        .clearfloat .chat-message{
            max-width: 252px;
            text-align: left;
            padding: 8px 12px;
            border-radius: 6px;
            word-wrap:break-word;
            display: inline-block;
            position: relative;
        }


        .clearfloat .left .chat-message{
            background: #D9D9D9;
            min-height: 36px;
        }
        .clearfloat .left .chat-message:before{
            position: absolute;
            content: "";
            top: 8px;
            left: -6px;
            border-top: 10px solid transparent;
            border-bottom: 10px solid transparent;
            border-right: 10px solid #D9D9D9;
        }

        .clearfloat .right{
            text-align: right;
        }
        .clearfloat .right .chat-message{
            background: #8c85e6;
            color: #fff;
            text-align: left;
            min-height: 36px;
        }
        .clearfloat .right .chat-message:before{
            position: absolute;
            content: "";
            top: 8px;
            right: -6px;
            border-top: 10px solid transparent;
            border-bottom: 10px solid transparent;
            border-left: 10px solid #8c85e6;
        }

        .clearfloat .chat-avatars{
            display: inline-block;
            width: 30px;
            height: 30px;
            border-radius: 50%;
            background: #eee;
            vertical-align: top;
            overflow: hidden;
        }
        .clearfloat .chat-avatars>img{
            width: 30px;
            height: 30px;
        }
        .clearfloat .left .chat-avatars{
            margin-right: 10px;
        }
        .clearfloat .right .chat-avatars{
            margin-left: 10px;
        }

        .chatBox-send{
            width: 100%;
            padding: 10px 5px;
            background: #eee;
            border-top: 1px #D0D0D0 solid;
            position: absolute;
            bottom: 0;
            left: 0;
        }

        .chatBox-send>div{
            float: left;
        }
        .chatBox-send>div:nth-of-type(2){
            font-size: 0;
        }
        .chatBox-send>div button{
            padding: 1px 5px;
            margin-left: 3px;
        }
        .chatBox-send>div label{
            padding: 1px 5px;
            margin-left: 3px;
        }
        #chat-biaoqing{
            position: relative;

        }
        .hidden{
            display: none;
        }
        .biaoqing-photo{
            width: 200px;
            height: 160px;
            background: #ffffff;
            position: absolute;
            top: -160px;
            right: 40px;
            text-align: left;
            border-radius: 5px;
            border: solid 1px #c5c5c5;
            display: none;
        }
        .biaoqing-photo::before{
            content: '';
            position: absolute;
            border-top: solid 7px #c5c5c5;
            border-left: solid 9px transparent;
            border-right: solid 9px transparent;
            bottom: -7px;
            right: 36px;
        }
        .biaoqing-photo::after{
            content: '';
            position: absolute;
            border-top: solid 7px #fff;
            border-left: solid 10px transparent;
            border-right: solid 10px transparent;
            bottom: -5px;
            right: 35px;
        }
        .biaoqing-photo>ul{
            margin: 0;
            width: 200px;
            height: 160px;
            padding: 3px 2px;
            list-style: none;
        }
        .biaoqing-photo>ul>li{
            float: left;
            height: 30px;
            margin-left: 2px;
        }
        .emoji-picker-image{
            display: inline-block;
            width: 30px;
            height: 30px;
            background: url(/static/httpchat/img/bqxtb01.png) no-repeat;
            background-size: 200px auto;
            cursor: pointer;
        }
        .biaoqing-photo>ul>li span.emoji-picker-image:hover{
            border: solid 1px #f5f5f5;
        }
        .chat-message img{
            width: 220px;
            height:auto;
        }

        .chat-name{
            width: 230px;
        }

        /*按钮样式*/
        .btn-default-styles {
            outline: none;
            resize: none;
            border: none;
            display: inline-block;
            padding: 5px 10px;
            margin-bottom: 0;
            font-size: 14px;
            font-weight: 400;
            line-height: 1.42857143;
            text-align: center;
            white-space: nowrap;
            vertical-align: middle;
            -ms-touch-action: manipulation;
            touch-action: manipulation;
            cursor: pointer;
            -webkit-user-select: none;
            -moz-user-select: none;
            -ms-user-select: none;
            user-select: none;
            background-image: none;
            background: #bbb;
            color: #fff;
            border-radius: 4px;
        }
        .btn-default-styles:focus {
            outline: none;
        }
        .btn-default-styles:hover {
            background: #c5c5c5;
            animation: anniu 1s infinite;
        }
        .btn-default-styles:active {
            box-shadow: 0 2px 3px rgba(0, 0, 0, .2) inset;
        }

        /* 设置滚动条的样式 */
        ::-webkit-scrollbar {
            width:5px;
        }
        /* 滚动槽 */
        ::-webkit-scrollbar-track {
            border-radius:10px;
        }
        /* 滚动条滑块 */
        ::-webkit-scrollbar-thumb {
            border-radius:10px;
            background:#8C85E6;
            -webkit-box-shadow:#8C85E6;
        }
        ::-webkit-scrollbar-thumb:window-inactive {
            background: rgba(175, 190, 255, 0.4);
        }

        @media all and (max-width: 768px) {
            .chatBox{
                position: fixed;
                top: 0;
                left: 0;
                width: 100%;
                height: 100%;
            }
        }
        @media all and (max-width: 370px){
            .chat-name{
                width: 185px;
            }
            .chat-people>div:nth-of-type(2){
                width: 120px;
            }
            .clearfloat .chat-message{
                max-width: 240px;
            }
        }
    </style>
</head>
<body>
<div class="layui-fluid" style="padding: 0">
    <div class="layui-row" style="overflow: hidden;">
        <div class="layui-col-md3 layui-col-lg3 layui-col-xs3 div-user" style="border-right: 1px solid #b4b2b2;height: 549px;overflow-y: scroll;">
            <ul class="userlist" id="chatuser">
                <li lay-id="1">
                    <img src="//tva1.sinaimg.cn/crop.0.0.118.118.180/5db11ff4gw1e77d3nqrv8j203b03cweg.jpg" alt="">
                    <span class="chat-name">管理员</span>
                    <span class="message-num">20</span>
                </li>
            </ul>
        </div>
        <div class="layui-col-md9 layui-col-lg9 layui-col-xs9 ">
            <div id="chatcontent">
                <div class="ChatInfoName">这里是用户昵称</div>
                <div>
                    <div class="chatBox-content">
                        <div class="chatBox-content-demo" id="chatBox-content-demo">


                        </div>
                    </div>
                    <div class="chatBox-send">
                        <div class="div-textarea" contenteditable="true"></div>
                        <div>
                            <button id="chat-biaoqing" class="btn-default-styles">
                                <i class="iconfont icon-biaoqing"></i>
                            </button>
                            <label id="chat-tuxiang" title="发送图片" for="inputImage" class="btn-default-styles">
                                <input type="file" onchange="selectImg(this)" accept="image/jpg,image/jpeg,image/png"
                                       name="file" id="inputImage" class="hidden">
                                <i class="iconfont icon-tuxiang"></i>
                            </label>
                            <button id="chat-fasong" class="btn-default-styles"><i class="iconfont icon-fasong"></i>
                            </button>
                        </div>
                        <div class="biaoqing-photo">
                            <ul>
                                <li><span class="emoji-picker-image" style="background-position: -9px -18px;"></span></li>
                                <li><span class="emoji-picker-image" style="background-position: -40px -18px;"></span></li>
                                <li><span class="emoji-picker-image" style="background-position: -71px -18px;"></span></li>
                                <li><span class="emoji-picker-image" style="background-position: -102px -18px;"></span></li>
                                <li><span class="emoji-picker-image" style="background-position: -133px -18px;"></span></li>
                                <li><span class="emoji-picker-image" style="background-position: -164px -18px;"></span></li>
                                <li><span class="emoji-picker-image" style="background-position: -9px -52px;"></span></li>
                                <li><span class="emoji-picker-image" style="background-position: -40px -52px;"></span></li>
                                <li><span class="emoji-picker-image" style="background-position: -71px -52px;"></span></li>
                                <li><span class="emoji-picker-image" style="background-position: -102px -52px;"></span></li>
                                <li><span class="emoji-picker-image" style="background-position: -133px -52px;"></span></li>
                                <li><span class="emoji-picker-image" style="background-position: -164px -52px;"></span></li>
                                <li><span class="emoji-picker-image" style="background-position: -9px -86px;"></span></li>
                                <li><span class="emoji-picker-image" style="background-position: -40px -86px;"></span></li>
                                <li><span class="emoji-picker-image" style="background-position: -71px -86px;"></span></li>
                                <li><span class="emoji-picker-image" style="background-position: -102px -86px;"></span></li>
                                <li><span class="emoji-picker-image" style="background-position: -133px -86px;"></span></li>
                                <li><span class="emoji-picker-image" style="background-position: -164px -86px;"></span></li>
                                <li><span class="emoji-picker-image" style="background-position: -9px -120px;"></span></li>
                                <li><span class="emoji-picker-image" style="background-position: -40px -120px;"></span></li>
                                <li><span class="emoji-picker-image" style="background-position: -71px -120px;"></span></li>
                                <li><span class="emoji-picker-image" style="background-position: -102px -120px;"></span></li>
                                <li><span class="emoji-picker-image" style="background-position: -133px -120px;"></span></li>
                                <li><span class="emoji-picker-image" style="background-position: -164px -120px;"></span></li>
                                <li><span class="emoji-picker-image" style="background-position: -9px -154px;"></span></li>
                                <li><span class="emoji-picker-image" style="background-position: -40px -154px;"></span></li>
                                <li><span class="emoji-picker-image" style="background-position: -71px -154px;"></span></li>
                                <li><span class="emoji-picker-image" style="background-position: -102px -154px;"></span></li>
                                <li><span class="emoji-picker-image" style="background-position: -133px -154px;"></span></li>
                                <li><span class="emoji-picker-image" style="background-position: -164px -154px;"></span></li>
                            </ul>
                        </div>
                    </div>
                </div>
            </div>

        </div>
    </div>
</div>

<!--<div class="layui-fluid">-->
<!--    ……-->
<!--</div>-->



</body>
</html>
<script>

    var myavatars = '';
    var myDate =new Date();
    var year=myDate.getFullYear(); //获取当前年份
    var mon=myDate.getMonth()+1; //获取当前月份
    var da=myDate.getDate(); //获取当前日
    var day=myDate.getDay(); //获取当前星期几
    var h=myDate.getHours(); //获取小时
    var m=myDate.getMinutes(); //获取分钟
    var s=myDate.getSeconds(); //获取秒
    var ms=myDate.getMilliseconds();	//获取当前毫秒数(0-999)
    var ld=myDate.toLocaleDateString();	//获取当前日期
    var msgdate=year+'-'+mon+'-'+da+' '+h+':'+m+':'+s;

    

    var from_id = "{$from_id}";
    var to_id = "{$to_id}";

    //进聊天页面
    $("#chatuser li").each(function () {
        $(this).click(function () {
            $("#chatuser li").css('background','rgb(0 0 0 / 5%)')
            $(this).css('background','#ffffff')
            var n = $(this).index();
            to_id = $(this).attr('lay-id')
            // $(".chatBox-head-one").toggle();
            // $(".chatBox-head-two").toggle();
            // $(".chatBox-list").fadeToggle();
            // $(".chatBox-kuang").fadeToggle();

            //传名字
            $(".ChatInfoName").text($(this).children(".chat-name").eq(0).html());

            //赋值头像
            myavatars = $(this).children('img').eq(0).attr("src");
            // //传头像

            //聊天框默认最底部
            $(document).ready(function () {
                $("#chatBox-content-demo").scrollTop($("#chatBox-content-demo")[0].scrollHeight);
            });
            // // 打开websocket
            // webSocket.onopen = function (event) {
            onOpen();
            // };
        })
    });
    // var userlist = [10009,10010,10011,10012,10013,10014,10015,10016,10017];
    /**
     0:未连接
     1:连接成功,可通讯
     2:正在关闭
     3:连接已关闭或无法打开
     */
        //创建一个webSocket 实例
    var webSocket = new WebSocket("ws://192.168.0.113:2345");
    webSocket.onerror = function (event) {
        onError(event);
    };
    // 打开websocket
    webSocket.onopen = function (event) {
        onOpen(event);
    };
    //监听消息
    webSocket.onmessage = function (event) {
        onMessage(event);
    };
    webSocket.onclose = function (event) {
        onClose(event);
    }
    //关闭监听websocket
    function onError(event) {
        // document.getElementById("msg").innerHTML = "<p>关闭</p>";
        console.log("错误: " + event.data);
    }
    function onOpen(event) {
        // console.log("打开: "+sockState());
        var bild = '{"type":"bind","uid":"' + from_id + '"}';
        webSocket.send(bild);
      
        setInterval(function () {
            webSocket.send('heartbeat');    //发送内容不限,只是为了证明客户端还没关闭还在线
        }, 20000)                    //50秒发一次
    }
    function onMessage(event) {
        // console.log(event.data)
        var massage = eval("(" + event.data + ")");

        //这里表示一对一聊天
        if (massage.type == 'text' && massage.mode == 'single') {
            //当前正在聊天的人  如果当前的发送对象id等于该消息来源的id,则为一个人  ,
            if (this.to_id == massage.from_id) {
                // console.log("服务端消息:"+massage.content);
                // $("#chatBox-content-demo").append("<div>我是" + massage.from_id + ":" + massage.content + "</div>");
                $("#chatBox-content-demo").append("<div class=\"clearfloat\">\n" +
                    "                                <div class=\"author-name\">\n" +
                    "                                    <small class=\"chat-date\">"+ massage.datetime +"</small>\n" +
                    "                                </div>\n" +
                    "                                <div class=\"left\">\n" +
                    "                                    <div class=\"chat-avatars\"><img src=\"" + myavatars + "\" alt=\"头像\"/></div>\n" +
                    "                                    <div class=\"chat-message\">" + massage.content + "</div>\n" +
                    "                                </div>\n" +
                    "                            </div>");
                return;
            } else {
                //不是当前聊天的人、将消息提醒发送到对应的列表,并将消息发送到对应页面
                //在数据库请求该人的基本信息,
            }

        }
        //这里表示群聊
        if (massage.type == 'text' && massage.mode == 'group') {

            console.log(massage);
        }

    }
    function onClose(event) {
        // document.getElementById("msg").innerHTML = "<p>他通讯已关闭</p>";
        console.log("关闭: " + sockState());
        webSocket.close();
    }
    function sockState() {
        var status = ['未连接', '连接成功,可通讯', '正在关闭', '连接已关闭或无法打开'];
        return status[webSocket.readyState];
    }
   
    function close(event) {
        webSocket.close();
    }
    document.onkeydown = keyDownSearch;
    function keyDownSearch(e) {
        // 兼容FF和IE和Opera
        var theEvent = e || window.event;
        var code = theEvent.keyCode || theEvent.which || theEvent.charCode;
        if (code == 13) {
            //具体处理函数
            chat_fasong()
            return false;
        }
        return true;
    }


    //未读信息数量为空时
    var totalNum = $(".chat-message-num").html();
    if (totalNum == "") {
        $(".chat-message-num").css("padding", 0);
    }
    $(".message-num").each(function () {
        var wdNum = $(this).html();
        if (wdNum == "") {
            $(this).css("padding", 0);
        }
    });



    //      发送信息
    $("#chat-fasong").click(function () {
        chat_fasong()
    });
    function chat_fasong() {
        var textContent = $(".div-textarea").html().replace(/[\n\r]/g, '<br>')
        if (textContent != "") {
            //发送到服务器
            var msg1 = '{"type":"text","mode":"single","from_id":"' + from_id + '","to_id":"' + to_id + '","content":"' + textContent + '","datetime":"' + msgdate + '"}';
            webSocket.send(msg1);
            $(".chatBox-content-demo").append("<div class=\"clearfloat\">" +
                "<div class=\"author-name\"><small class=\"chat-date\">" + msgdate + "</small> </div> " +
                "<div class=\"right\"> <div class=\"chat-message\"> " + textContent + " </div> " +
                "<div class=\"chat-avatars\"><img src=\"/static/httpchat/img/icon01.png\" alt=\"头像\" /></div> </div> </div>");
            /*"/static/httpchat/img/icon01.png"*/
            //发送后清空输入框
            $(".div-textarea").html("");
            //聊天框默认最底部
            $(document).ready(function () {
                $("#chatBox-content-demo").scrollTop($("#chatBox-content-demo")[0].scrollHeight);
            });
        }
    }

    //      发送表情
    $("#chat-biaoqing").click(function () {
        $(".biaoqing-photo").toggle();
    });
    $(document).click(function () {
        $(".biaoqing-photo").css("display", "none");
    });
    $("#chat-biaoqing").click(function (event) {
        event.stopPropagation();//阻止事件
    });

    $(".emoji-picker-image").each(function () {
        $(this).click(function () {
            var bq = $(this).parent().html();
            //发送到服务器
            var msg2 = '{"type":"text","mode":"single","from_id":"' + from_id + '","to_id":"' + to_id + '","content":"' + bq + '","datetime":"' + msgdate + '"}';
            webSocket.send(msg2);
            $(".chatBox-content-demo").append("<div class=\"clearfloat\">" +
                "<div class=\"author-name\"><small class=\"chat-date\">"+ msgdate +"</small> </div> " +
                "<div class=\"right\"> <div class=\"chat-message\"> " + bq + " </div> " +
                "<div class=\"chat-avatars\"><img src=\"/static/httpchat/img/icon01.png\" alt=\"头像\" /></div> </div> </div>");
            //发送后关闭表情框
            $(".biaoqing-photo").toggle();
            //聊天框默认最底部
            $(document).ready(function () {
                $("#chatBox-content-demo").scrollTop($("#chatBox-content-demo")[0].scrollHeight);
            });
        })
    });

    //      发送图片
    function selectImg(pic) {
        if (!pic.files || !pic.files[0]) {
            return;
        }
        var reader = new FileReader();
        reader.onload = function (evt) {
            var images = evt.target.result;
            var to_img = "<img src=" + images + ">";
            //发送到服务器
            var msg3 = '{"type":"text","mode":"single","from_id":"' + from_id + '","to_id":"' + to_id + '","content":"' + to_img + '","datetime":"' + msgdate + '"}';
            webSocket.send(msg3);

            $(".chatBox-content-demo").append("<div class=\"clearfloat\">" +
                "<div class=\"author-name\"><small class=\"chat-date\">"+ msgdate +"</small> </div> " +
                "<div class=\"right\"> <div class=\"chat-message\"><img src=" + images + "></div> " +
                "<div class=\"chat-avatars\"><img src=\"/static/httpchat/img/icon01.png\" alt=\"头像\" /></div> </div> </div>");
            //聊天框默认最底部
            $(document).ready(function () {
                $("#chatBox-content-demo").scrollTop($("#chatBox-content-demo")[0].scrollHeight);
            });fu
        };
        reader.readAsDataURL(pic.files[0]);

    }

</script>

附上php整体代码:

<?php
declare (strict_types=1);

namespace app\http;

use app\common\model\ClubUser;
use app\common\model\UserChat;
use app\common\model\UserClubChat;
use think\facade\Cache;
use think\facade\Db;
use think\facade\Log;
use think\worker\Server;
use Workerman\Lib\Timer;

// define('HEARTBEAT_TIME', 30);// 心跳间隔
class Worker extends Server
{
    protected $socket = 'websocket://0.0.0.0:2345';

    protected $redis;

    protected static $heartbeat_time = 50;

    public function onConnect($connection)
    {
        $this->redis = Cache::store('redis');
    }

    public function onWorkerStart($worker)
    {
        Timer::add(10, function () use ($worker) {
            $time_now = time();
            #这里统计下线人员的id
            $offline_user = [];

            foreach ($worker->connections as $connection) {
                // 有可能该connection还没收到过消息,则lastMessageTime设置为当前时间
                if (empty($connection->lastMessageTime)) {
                    $connection->lastMessageTime = $time_now;
                    continue;
                }
                // 上次通讯时间间隔大于心跳间隔,则认为客户端已经下线,关闭连接
                // if ($time_now - $connection->lastMessageTime > HEARTBEAT_TIME) {
                if ($time_now - $connection->lastMessageTime > self::$heartbeat_time) {
                    #这里统计下线人员的id
                    $offline_user[] = $connection->uid;
                    #关闭连接
                    $connection->close();
                }

                #这里是一个用户下线后通知其他用户
                if (count($offline_user) > 0) {
                    $msg = ['type' => 'message', 'uid' => $connection->uid, "message" => "用户【" . implode(',', $offline_user) . "】下线了"];
                    $connection->send(json_encode($msg));
                }
            }
        });
    }

    public function onMessage($connection, $data)
    {
        #最后接收消息时间
        $connection->lastMessageTime = time();
        $msg_data = json_decode($data, true);
        if (!$msg_data) {
            return;
        }

        Log::error($msg_data);

        #这里统计上线人员的id
        $online_user = [];

        $issee = 0;
        if ($msg_data['type'] == 'bind') {
            $from_id = $msg_data['uid'];
            $to_id = $msg_data['to_uid'];
        } else {
            $from_id = $msg_data['from_id'];
            $to_id = $msg_data['to_id'];
        }

        Log::error($this->redis->get('uid_' . $from_id));

        if (!$this->redis->get('uid_' . $from_id)) {
            $this->redis->set('uid_' . $from_id, $to_id);
            if ($this->redis->get('uid_' . $to_id) == $from_id) {
                $issee = 1;
            }
        } else {
            if ($this->redis->get('uid_' . $from_id) == $to_id && $this->redis->get('uid_' . $to_id) == $from_id) {
                $issee = 1;
            }
        }

        #绑定用户ID
        if ($msg_data['type'] == 'bind' && isset($msg_data['to_uid']) && !isset($connection->uid)) {
            $connection->uid = $msg_data['uid'];
            $online_user[] = $connection->uid;
            $this->uidConnections[$connection->uid] = $connection;
        } else if ($msg_data['type'] == 'text' && $msg_data['mode'] == 'single') {
            #单人发消息
            if($this->redis->get('uid_' . $to_id) == $from_id){
                if (isset($this->uidConnections[$msg_data['to_id']])) {
                    $conn = $this->uidConnections[$msg_data['to_id']];
                    $conn->send($data);
                }
            }
        }

        if ($msg_data['type'] == 'text' && $msg_data['mode'] == 'single'){
            if ($msg_data['content'] != '' && $msg_data['content'] != null) {
                $second = 0;
                if ($msg_data['is_audio'] == true) {
                    //证明是音频
                    $second = $this->getAudioSeond($msg_data['content']);
                }
                //将发来的信息保存到数据库
                $info = [
                    'user_id' => $msg_data['from_id'],
                    'be_user_id' => $msg_data['to_id'],
                    'content' => $msg_data['content'],
                    'is_type' => $msg_data['is_type'],
                    'second' => $second,
                    'is_see' => $issee,
                ];
                UserChat::create($info);
            }
        }

		//俱乐部
        if ($msg_data['type'] == 'bind' && isset($msg_data['club_id']) && !isset($connection->uid)) {
            $connection->uid = $msg_data['uid'];
            $online_user[] = $connection->uid;
            $this->uidConnections[$connection->uid] = $connection;
        }

        #群聊
        if ($msg_data['type'] == 'text' && $msg_data['mode'] == 'group') {
            #实际项目通过群号查询群里有哪些用户
            //俱乐部成员
            $club_user = ClubUser::where(['club_id' => $msg_data['club_id'], 'to_examine' => 1, 'status' => 0, 'delete_time' => 0])->column('user_id');
            foreach ($club_user as $key => $val) {
                if ($val != $msg_data['from_id']) {
                    if (isset($this->uidConnections[$val])) {
                        $conn = $this->uidConnections[$val];
                        $conn->send($data);
                    }
                }

            }
            if ($msg_data['content'] != '' && $msg_data['content'] != null) {
                $second = 0;
                if ($msg_data['is_audio'] == true) {
                    //证明是音频
                    $second = $this->getAudioSeond($msg_data['content']);
                }
                //将发来的信息保存到数据库 俱乐部
                $info = [
                    'user_id' => $msg_data['from_id'],
                    'club_id' => $msg_data['club_id'],
                    'content' => $msg_data['content'],
                    'is_type' => $msg_data['is_type'],
                    'second' => $second,
                    'is_see' => 0,
                ];
                UserClubChat::create($info);
            }

        }
    }
	
	//获取音频时常
    public function getAudioSeond($path)
    {
        include_once app()->getRootPath() . 'vendor/getID3-master/getid3/getid3.php';
        $getID3 = new \getID3();//实例化类
        $path = app()->getRootPath() . 'public' . $path;
        $ThisFileInfo = $getID3->analyze($path);//分析文件,$path为音频文件的地址
        $fileduration = $ThisFileInfo['playtime_seconds'];//这个获得的便是音频文件的时长
        $time = (int)ceil($fileduration);
        return $time;
    }

    /**
     * 当连接断开时触发的回调函数
     */
    public function onClose($connection)
    {
        $this->redis->delete('uid_' . $connection->uid);
    }

}

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐