workerman webman+GatewayWorker实现聊天室demo实例

羊舌志
2023-12-01

workerman webman+GatewayWorker实现聊天室demo实例

说明

最近先来无事发现workerman的webman作为web框架很不错,想着写一个demo。于是就动手了,本人前端不太好,所以页面较丑,不要介意哈哈哈。

官方文档

https://www.workerman.net/

workerman 真的很不错,社区环境也不错,基本上有问题都有答复。有时间我也会多研究下,后面也会分享出来

重磅

demo地址: https://gitee.com/xiaoqiaoniubi/my-webman-chat

  1. 先下载下项目,将根目录下的webman-chat.sql 导入至数据库,数据库名称为:webman-chat。可在数据库配置文件中修改
  2. 执行 composer install
  3. windows环境:直接双击根目录下的windows.bat的文件,并在网站中访问localhost:8787
  4. linux环境:防火墙等开放7272端口(websocket),在根目录上执行 php start.php start

代码片段

  1. 服务端监听websocket:
    位置:根目录/plugin/webman/gateway/Events.php
    public static function onWebSocketConnect($client_id, $data)
    {
        // 拿到连接时携带的token 查询uid
        $getData = $data['get'];
        $userModel = new User();
        $userInfo = $userModel -> getUserInfoByToken($getData['token']);
        if (empty($userInfo)) { // token过期
            send($client_id,'账号信息错误,请重新登录',[
                'type' => MsgType::LOGIN_ERROR,
            ]);
            sleep(1); // 延迟一秒断开链接
            return Gateway::closeClient($client_id);
        }
        $uid = $userInfo -> id;
        // 重复上线验证
        if (count(Gateway::getClientIdByUid($uid)) > 0) {
            send($client_id,'当前账号已在线,请换个账号',[
                'type' => MsgType::ERROR,
            ]);
            sleep(1); // 延迟一秒断开链接
            return Gateway::closeClient($client_id);
        }
        // uid 绑定 client_id
        Gateway::bindUid($client_id,$uid);
        // 用户是否创建过房间,是否显示创建房间 or 我的房间 按钮
        $roomModel = new Room();
        $roomInfo = $roomModel -> getUserRoom($uid);
        $roomList = $roomModel -> getRoomListByIds();
        send($client_id,'连接成功',[
            'client_id' => $client_id,
            'type' => MsgType::LOGIN,
            'room_id' => empty($roomInfo) ? 0 : $roomInfo -> id,
            'room_list' => $roomList,
        ]);
    }

    public static function onMessage($client_id, $message)
    {
        $message = json_decode($message,true);
        $data = $message['data'] ?? [];
        switch ($message['type']) {
            case MsgType::JOIN: // 加入房间
                $userModel = new User();
                $userInfo = $userModel -> getUserInfoByToken($data['token']);
                // 加入房间
                Gateway::joinGroup($client_id,$data['room_id']);
                // 获取房间列表
                $roomUserList = Gateway::getUidListByGroup($data['room_id']);
                $finalUserList = [];
                foreach ($roomUserList as $key => $val) {
                    // 查询用户昵称
                    $userInfo = $userModel -> getUserInfoByUid($val);
                    $finalUserList[] = ['user_id' => $val,'nickname' => empty($userInfo) ? '未知用户' : $userInfo -> nickname];
                }
                // 向房间广播
                send_to_group($data['room_id'],'请求成功',[
                    'type' => MsgType::JOIN,
                    'nickname' => $userInfo -> nickname,
                    'online_num' => count($finalUserList),
                    'online_list' => $finalUserList,
                ]);
                break;
            case MsgType::SEND_MSG:
                $userModel = new User();
                $userInfo = $userModel -> getUserInfoByToken($data['token']);
                // 广播到房间
                send_to_group($data['room_id'],'请求成功',[
                    'type' => MsgType::SEND_MSG,
                    'send_user_nickname' => $userInfo -> nickname,
                    'send_user_id' => $userInfo -> id,
                    'send_content' => $data['content'],
                ]);
                break;
            default:
                send($client_id,'请求成功',['client_id' => $client_id]);
                break;
        }
    }

  1. 客户端监听服务端websocket:
    位置:根目录/public/static/chat_js/base.js
function onmessage(e) {
    var data = JSON.parse(e.data);
    var fullData = data;
    data = data.data;
    switch(data.type){
        case 'login':
            // 当前用户有房间则显示进入入口,否则显示创建入口
            if (data.room_id > 0) {
                $('.create_room .join_room').attr('data-room-id',data.room_id);
                $('.create_room .join_room').show();
                $('.do_create_room').hide();
            } else {
                $('.create_room .join_room').hide();
                $('.do_create_room').show();
            }
            client_id = data.client_id;
            // 房间列表更新
            $('.room_list').empty();
            var roomDom = '';
            $.each(data.room_list,function(i,val) {
                roomDom += '<a href="/index/joinRoom?room_id='+val.id+'">'+val.room_name+'</a><br/><br/>';
            });
            $('.room_list').append(roomDom);
            break;
        case 'join':
            $('.onlineNum').text(data.online_num);
            // 重新渲染房间列表
            $('.online_user_list').empty();
            var onlineUserDom = '';
            $.each(data.online_list, function(i,val){
                onlineUserDom += '<div class="pos">' +
                    '<span class="identity">用户'+(i+1)+':</span>' +
                    '<span class="nickname">'+val.nickname+' 已加入</span>' +
                    '</div>'
            });
            $('.online_user_list').append(onlineUserDom);
            break;
        case 'send_msg':
            var msgDom = '';
            msgDom += '<p class="content">'+data.send_user_nickname+' 说:'+data.send_content+'</p>';
            $('.msg_content').append(msgDom);
            break;
        case 'login_error':
            showLogin();
            break;
        default:
            break;
    }
}

结尾

大家有问题可以留言哦,不要吝啬star 和 点赞哦。

 类似资料: