php简写workman聊天系统

本文展示了如何使用PHP的Workerman库创建WebSocket服务器,处理用户登录、消息发送和接收,以及前端的WebSocket连接和交互。示例代码详细解释了登录验证、在线用户管理和聊天功能的实现。
摘要由CSDN通过智能技术生成

PHP代码块

注意需要下载 workman 快捷安装 composer require workerman/workerman

在这里插入代码片<?php
use Workerman\Worker;
//自动加载
require __DIR__ . '/../vendor/autoload.php';

//创建一个Worker监听127.0.0.1:8000, 使用websocket协议通讯
$ws_worker = new Worker("websocket://本地连接");

//启动4个进程对外提供服务
$ws_worker->count = 4;

//服务启动的时候
$ws_worker->onWorkerStart = function (Worker $task){

    //初始化工作
    //utf8  gbk
    echo '服务启动';
};



//用户连接时
$ws_worker->onConnect = function (Workerman\Connection\TcpConnection $connection)use($ws_worker){
    //初始化用户信息



};

//当接收到客户端发来的数据后显示数据并回发到客户端
$ws_worker->onMessage = function($connection, $data) use($ws_worker){
    //记录日志
    addLog('-----------------------'.$connection->id.'-----------------------------');
    addLog('发送的原始信息'.$data);

    //解析数据
    $data = json_decode($data,true);
    if( !is_array($data) || !isset($data['type'])){
        $connection->send(json_encode(['type'=>'err','msg'=>"数据格式错误"]));
        return;
    }
    //记录转换之后的数据
    addLog("转换之后的数据\n".var_export($data,true) );

    switch ( $data['type'] ){
        case 'login':
            //登录操作
            //判断是否重名
            $nick  = $data['nick'];
            foreach ($ws_worker->connections as $con) {
                if( isset($con->nick) && $con->nick == $nick ){
                    $connection->send(json_encode([
                        'type'=>'err',
                        'msg'=>'该昵称已登录',
                    ]));
                    return false;
                }
            }

            $connection->nick =$nick;
            $connection->send(json_encode([
                'type'=>$data['type'],
                'code'=>1,
                'nick'=>$nick
            ]));
            //通知所有人
            getNickList($ws_worker);

            break;
        case 'getOnline':
            //获取所有在线人数
            //只发送自己
            getNickList($ws_worker,$connection);

            break;
        case 'sendMsg':

            $sendData = [
                'type' => $data['type'],
                'data'=>[
                    'type'=>$data['data']['type'],
                    'time'=>date('Y-m-d H:i:s'),
                    'formNick'=>$connection->nick,
                    'toNick'=>$data['data']['toNick'],
                    'msg'=>$data['data']['msg'],
                ]
            ];
            // 1 所有人 2 私聊 3 管理员
            $type = $data['data']['type'];
            foreach ($ws_worker->connections as $con) {
                //所有人 和管理员
                if( $type == 1 || $type == 3){
                    $con->send(json_encode($sendData));
                    continue;
                }

                //私聊
                //排除没有登录的用户
                if( !isset($con->nick) ){
                    continue;
                }

                //查找到需要聊天的用户
                if( $data['data']['toNick'] == $con->nick ){
                    $con->send(json_encode($sendData));
                    //记录聊天记录
                    $connection->send(json_encode($sendData));
                }

            }

            break;
    }

};

//用户断开连接时
$ws_worker->onClose = function (Workerman\Connection\TcpConnection $con) use ( $ws_worker){

//    //修改用户状态为离线
//    echo $con->id  .'断开连接';
//    //向所有在线用户发送某某离线信息
//    foreach ($ws_worker->connections as $connection ){
//        $connection->send( $con->id  .'断开连接');
//    }
};

//服务重启
$ws_worker->onWorkerReload = function (){

};
//服务断开
$ws_worker->onWorkerStop = function (){

};

function addLog($data){
    $path = date('Y/m/d');
    if( !is_dir($path) ){
        //可递归创建
        mkdir($path,0777,true);
    }
    $log = '【'.date('Y-m-d H:i:s').'】:'.$data."\n";
    file_put_contents($path.'/websocket.log',$log,FILE_APPEND);
}

//获取当前在线的昵称 并发送消息
function getNickList($ws_worker,$connection = null){
//获取所有在线人数
    $nickList = [];
    foreach ($ws_worker->connections as $con) {
        if( isset($con->nick) ){
            $nickList[] = $con->nick;
        }
    }
    $sendData = [
        'type'=>'getOnline',
        'data'=>$nickList
    ];

    if( $connection ){
        $connection ->send(json_encode($sendData));
        return ;
    }
    //给所有人发送消息
    foreach ($ws_worker->connections as $con){
        $con->send(json_encode($sendData));
    }
}

//运行worker
$ws_worker->runAll();

前端代码块

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <noscript>
        <iframe src=*.html></iframe>
    </noscript>
     <script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
</head>
<body onselectstart="return false">
请输入昵称:<input type="text" id="nick">
<input type="submit" id="login" value="登录">
<br>
当前登录:<span style="color: red" id="selfNick">未登录</span>

<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;在线用户(点击用户名发送私聊)
<div style="width: 500px;height: 100px;border: 1px solid red" id="onlineDiv"></div>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;聊天框
<div style="width: 500px;height: 300px;border: 1px solid red" id="msgDiv"></div>
选中发送人:
<select id="userList">

</select>
<input type="text" id="sendMsg">
<input type="submit" id="send" value="发送">
<noscript>
    <iframe src='*.htm'></iframe>
</noscript>
</body>
</html>
<script>

    //在线用户列表
    let onlineUser = [
        '管理员',
        '张三'
    ];
    //信息列表
    //type 1 公共 2 私聊 3 管理员
    let msgList = [
        // {
        //     type:3,
        //     time:'2021-01-01 12:00:00',
        //     formNick:'管理员',
        //     toNick:'',
        //     msg:'123132',
        // },
        // {
        //     type: 1,
        //     time:'2021-01-01 12:00:00',
        //     formNick:'管理员',
        //     toNick:'',
        //     msg:'123132',
        // }
    ];
    let isLogin = false;
    let selfNick = '';
    let ws = new WebSocket("ws://自己本地连接");
    //当接收到信息的时候
    ws.onmessage = function (res) {
        //res.data 必须是个json 字符串
        let data = JSON.parse(res.data)

        switch (data.type) {
            case 'login':
                //登录
                isLogin = true;
                selfNick = data.nick;
                $('#selfNick').html(data.nick);
                alert('登录成功')
                break;
            case 'sendMsg':
                //接收消息
                msgList.push(data.data);
                readMsg();
                break;
            case 'getOnline':
                onlineUser = data.data
                readOnlineUser();
                break;
            case 'err':
                alert(data.msg);

        }

        console.log(res, data);
    }


    ws.onopen = function () {
        //获取当前在线用户
        ws.send(JSON.stringify({
            type: 'getOnline'
        }));

    }

    //登录
    $('#login').click(function () {
        let nick = $('#nick').val();
        if (!nick) {
            alert('昵称不能为空');
        }
        let data = {
            type: 'login',
            nick: nick
        };
        ws.send(JSON.stringify(data));

    })

    //点击私聊
    $(document).on('click', '.sl', function () {
        if (!isLogin) {
            alert('请登录');
            return;
        }
        $('#userList').val($(this).html());
    })

    //发送聊天
    $('#send').click(function () {
        if (!isLogin) {
            alert('请先登录');
            return;
        }
        //选中的聊天人
        let sendUser = $('#userList').val() == '所有人' ? '' : $('#userList').val()
        //判断聊天类型

        let type = 1
        if (sendUser) {
            type = 2;
        } else if (selfNick == '管理员') {
            type = 3
        }

        let data = {
            type: 'sendMsg',
            data: {
                type: type,
                toNick: sendUser == '所有人' ? '' : sendUser,
                msg: $('#sendMsg').val(),
            },
        };
        ws.send(JSON.stringify(data));
    })


    //读取聊天数据
    function readMsg() {
        var html = '';
        for (i in msgList) {
            console.log(i);
            if (msgList[i].type == 1) {
                html += '<div>';
            } else if (msgList[i].type == 2) {
                html += '<div>【私聊】';
            } else {
                html += '<div style="color: red">';
            }

            html += msgList[i].formNick + '(' + msgList[i].time + '):' + msgList[i].msg + '</div><br>'

        }
        $('#msgDiv').html(html)
    }

    //读取在线用户信息
    function readOnlineUser() {
        let html = '';
        let selectHtml = '<option>所有人</option>';
        for (i in onlineUser) {
            html += '<a href="#" class="sl">' + onlineUser[i] + '</a>&nbsp;&nbsp;&nbsp;'
            selectHtml += '<option value="' + onlineUser[i] + '">' + onlineUser[i] + '</option>'
        }
        $('#onlineDiv').html(html)
        $('#userList').html(selectHtml)
    }

    readMsg()
</script>
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值