C++项目——集群聊天服务器项目(八)用户登录业务

news2024/11/30 18:55:02

在第(7)节中,已经实现用户注册模块,本节来实现用户登录模块

项目流程

1、项目环境搭建 

C++项目——集群聊天服务器项目(一)项目介绍、环境搭建、Boost库安装、Muduo库安装、Linux与vscode配置_c++集群聊天服务器-CSDN博客

2、Json第三方库介绍

C++项目——集群聊天服务器项目(二)Json第三方库-CSDN博客

3、muduo网络库介绍

C++项目——集群聊天服务器项目(三)muduo网络库-CSDN博客

4、MySQL数据库创建

C++项目——集群聊天服务器项目(四)MySQL数据库-CSDN博客

5、网络模块与业务模块代码编写

C++项目——集群聊天服务器项目(五)网络模块与业务模块-CSDN博客

6、MySQL模块编写

C++项目——集群聊天服务器项目(六)MySQL模块-CSDN博客

7、Model层设计、注册业务实现

C++项目——集群聊天服务器项目(七)Model层设计、注册业务实现-CSDN博客

一、用户登录业务实现步骤

用户登录业务步骤:

(1)从json对象中获取id和password,用于登录

注:json获取到的是字符串,user表中id为int类型,要将json获取的id转为int类型

(2)调用UserModel类对象中的查询函数,输入id,返回User对象,如果用户不存在返回空对象

(3)判断返回用户id与json对象获取id、返回密码与json获取密码是否一致,分为以下两种情况

1)若一致,则证明数据库中存在该用户,又分为用户在线/不在线两种状态

<1>若用户在线,则不允许重复登录,返回登录响应信息与错误提示信息

<2>若用户不在线,则用户登录成功

这里会在chatservice.hpp中定义一个哈希表存储用户id及在线用户的通信连接,由于随时都可能有新用户连接与连接删除,而STL容器不保证线程安全,因此这里需要定义一个互斥锁,保证用户通信连接哈希表的线程安全。且仅需在插入和删除哈希表保证线程安全即可。

private:  
      //存储用户的通信连接
    unordered_map<int,TcpConnectionPtr> _userConnMap;

    //定义互斥锁,保证_userConnMap的线程安全
    mutex _connMutex;

如果用户登录成功,向哈希表中插入用户登录id及通信连接,使用互斥锁保证线程安全,即

            {
                // 登陆成功,记录用户连接
                lock_guard<mutex> lock(_connMutex);
                _userConnMap.insert(make_pair(id, conn));
            }

插入在线连接后,更新用户为在线状态,定义json对象返回登录响应信息及日志信息,并返回登录用户的姓名和id

注:其实此时应该判断用户是否有离线消息,但本节不进行实现,后续对其实现。

2)若不一致,则证明数据库中没有该用户,即用户名与密码错误

定义json对象,返回登录响应信息与错误提示信息

二、用户登录业务具体实现

include/server/chatservice.hpp中,定义互斥锁和通信连接哈希表

#ifndef CHATSERVICE_H
#define CHATSERVICE_H

#include <muduo/net/TcpConnection.h>
#include <unordered_map>//一个消息ID映射一个事件处理 
#include <functional>
#include <mutex>
using namespace std;
using namespace muduo;
using namespace muduo::net;

#include "usermodel.hpp"
#include "json.hpp"
using json = nlohmann::json;

//表示处理消息的事件回调方法类型,事件处理器,派发3个东西 
using MsgHandler = std::function<void(const TcpConnectionPtr &conn, json &js, Timestamp)>;

//聊天服务器业务类
class ChatService
{
public:
    //获取单例对象的接口函数
    static ChatService *instance();
    //处理登录业务
    void login(const TcpConnectionPtr &conn, json &js, Timestamp time);
    //处理注册业务
    void reg(const TcpConnectionPtr &conn, json &js, Timestamp time);

    //获取消息对应的处理器
    MsgHandler getHandler(int msgid);
private:
    ChatService();//单例 

    //存储消息id和其对应的业务处理方法,消息处理器的一个表,写消息id对应的处理操作 
    unordered_map<int, MsgHandler> _msgHandlerMap;

    //存储用户的通信连接
    unordered_map<int,TcpConnectionPtr> _userConnMap;

    //定义互斥锁,保证_userConnMap的线程安全
    mutex _connMutex;

    //数据操作类对象
    UserModel _userModel;

};

#endif

在public.hpp中定义登录响应消息

#ifndef PUBLIC_H
#define PUBLIC_H

/*
server和client的公共文件
*/
enum EnMsgType
{
    LOGIN_MSG = 1, //登录消息
    LOGIN_MSG_ACK, //登录响应消息   
    REG_MSG, //注册消息 
    REG_MSG_ACK, //注册响应消息
};

#endif

在src/server/chatservice.cpp中进行登录功能实现

// 处理登录业务  id  pwd   pwd
void ChatService::login(const TcpConnectionPtr &conn, json &js, Timestamp time)
{
    int id = js["id"].get<int>();
    string pwd = js["password"];
    User user = _userModel.query(id);
    if (user.getId() == id && user.getPwd() == pwd)
    {
        if (user.getState() == "online")
        {
            // 该用户已经登录,不允许重复登录
            json response;
            response["msgid"] = LOGIN_MSG_ACK;
            response["errno"] = 2;
            response["errmsg"] = "该账号已经登录,请重新输入新账号";
            conn->send(response.dump()); // 回调 ,返回json字符串
        }
        else
        {
            {
                // 登陆成功,记录用户连接
                lock_guard<mutex> lock(_connMutex);
                _userConnMap.insert(make_pair(id, conn));
            }

            // 登录成功,更新用户状态信息
            user.setState("online");
            _userModel.updateState(user);
            json response;
            response["msgid"] = LOGIN_MSG_ACK;
            response["errno"] = 0;
            response["errmsg"] = "登录成功!";
            response["id"] = user.getId();
            response["name"] = user.getName();

        }
    }
    else
    {
        // 用户名或者密码错误
        json response;
        response["msgid"] = LOGIN_MSG_ACK;
        response["errno"] = 1;
        response["errmsg"] = "用户名或者密码错误";
        conn->send(response.dump()); // 回调 ,返回json字符串
    }
}

三、登录业务验证

查表可以获取当前用户信息

我们使用张三的账号来登录,输入

{"msgid":1,"id":13,"password":"123456"}

登陆成功,回显用户id和姓名

张三在线的情况下,我们再次登录,错误日志显示该账号已经登录

接下来我们使用李四的id输入,但密码错误,验证功能是否正常运转

可以看到用户名或者密码错误,登录失败!

登录业务验证成功!

一起期待下一次项目的更新吧~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1555726.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux(5)底层分析-常见问题-经典笔试面试题整理

六、底层分析 1、linux 目录 Linux各路径的解释&#xff1a; /bin存放二进制可执行文件(ls,cat,mkdir等)&#xff0c;常用命令一般都在这里/home存放所有用户文件的根目录&#xff0c;是用户主目录的基点&#xff0c;比如用户user的主目录是/home/user&#xff0c;可以用~us…

iOS - Runtime - Class-方法缓存(cache_t)

文章目录 iOS - Runtime - Class-方法缓存(cache_t)1. 散列表的存取值 iOS - Runtime - Class-方法缓存(cache_t) Class内部结构中有个方法缓存&#xff08;cache_t&#xff09;&#xff0c;用散列表&#xff08;哈希表&#xff09;来缓存曾经调用过的方法&#xff0c;可以提高…

A fatal error occurred: MD5 of file does not match data in flash!问题解决

采用的芯片是ESP32-S3-WROOM&#xff0c;16MB FLASH 开发环境是Arduino&#xff0c;烧录到100%后直接报错。 以为是Arduino的问题&#xff0c;用esp-idf开发的程序&#xff0c; 烧录的过程中&#xff0c;也是直接报错如下&#xff1a; esptool.py v4.7.0 Serial port /dev/…

什么是缓冲区溢出攻击?

缓冲区是内存存储区域&#xff0c;在数据从一个位置传输到另一个位置时临时保存数据。当数据量超过内存缓冲区的存储容量时&#xff0c;就会发生缓冲区溢出&#xff08;或buffer overrun&#xff09;。结果&#xff0c;试图将数据写入缓冲区的程序会覆盖相邻的内存位置。 例如…

java组合总和2(力扣Leetcode40)

组合总和 II 力扣原题链接 问题描述 给定一个候选人编号的集合 candidates 和一个目标数 target&#xff0c;找出 candidates 中所有可以使数字和为 target 的组合。 每个数字在每个组合中只能使用一次。 注意&#xff1a;解集不能包含重复的组合。 示例 示例 1: 输入:…

【倪琴神品品鉴】全新倪诗韵神品级古琴

倪琴朱砂神品仲尼&#xff0c;仅此放漏一张&#xff1b;龙池侧签海门倪诗韵制&#xff0c;雁足上方刻“雷音琴坊”方章&#xff0c;凤沼下方有随形章“神品”二字&#xff1b;老木材纹理竖直&#xff0c;共振良好&#xff0c;是难得的佳器&#xff1b;附带倪老师亲笔签名收藏证…

【机器学习之---数学】随机游走

every blog every motto: You can do more than you think. https://blog.csdn.net/weixin_39190382?typeblog 0. 前言 随机游走 1. 概念 1.1 例1 在你的饮食俱乐部度过了一个富有成效的晚上后&#xff0c;你在不太清醒的状态下离开了。因此&#xff0c;你会醉醺醺地在展…

JUC:wait/notify用法并写一个简单消息队列(生产者消费者问题)

文章目录 wait/notifyapiwait vs sleep手写消息队列 wait/notify 这块比较简单&#xff0c;就不在把所有例子都写上了。 要注意区分waitSet和EntryList中的线程&#xff0c;一个获得了锁但是wait释放了锁进入等待notify唤醒状态&#xff0c;一个是正在等待获得锁。 不过相同点…

算法之并查集

并查集&#xff08;Union-find Data Structure&#xff09;是一种树型的数据结构。它的特点是由子结点找到父亲结点&#xff0c;用于处理一些不交集&#xff08;Disjoint Sets&#xff09;的合并及查询问题。 Find&#xff1a;确定元素属于哪一个子集。它可以被用来确定两个元…

wps斜线表头并分别打字教程

wps斜线表头怎么做并分别打字&#xff1a; 1、首先选中我们想要设置的表头。 2、接着右键选中它&#xff0c;点击“设置单元格格式” 3、然后点击上方“边框”选项卡。 4、随后选择图示的斜线&#xff0c;点击“确定” 5、设置完成后&#xff0c;我们只要在其中打字就可以在斜…

vue-v-for遍历index与id

一.遍历列表key的作用&#xff08;index作为key&#xff09; 虚拟DOM上有key,是虚拟的&#xff0c;但是真实DOM上没有&#xff0c;key是Vue内部的 当使用index作为key的时候&#xff0c;Vue会根据初识数据生成一个初始的虚DOM&#xff0c; 然后在页面上映射出真实DOM 如果向数据…

vue 窗口内容滚动到底部

onMounted(() > {scrollToBottom() }) // 滚动到底部方法 const scrollToBottom () > {// 获取聊天窗口容器let chatRoom: any document.querySelector(".chat-content");// 滚动到容器底部chatRoom.scrollTop chatRoom.scrollHeight; } 效果 聊天窗口代码…

HashMap关键源码带读

文章目录 目录 文章目录 前言 1 . 成员变量 灵魂五问 第一问: 默认初始化容量为啥是16? 第二问: 最大容量为什么必须是2的幂? 第三问: 链表转红黑树的阈值为什么是8? 第四问: 红黑树转链表的阈值为什么是6? 第五问: 默认加载因子为什么是0.75? 2. 成员方法 eq…

Discuz采集发布插件

Discuz&#xff08;简称DZ&#xff09;是一款知名的开源论坛系统&#xff0c;广泛应用于各类网站社区。对于许多站长来说&#xff0c;保持论坛内容的更新是一项挑战&#xff0c;特别是在内容量庞大的情况下。为了解决这个问题&#xff0c;有一类特殊的插件是用于在Discuz论坛中…

《QT实用小工具·四》屏幕拾色器

1、概述 源码放在文章末尾 该项目实现了屏幕拾色器的功能&#xff0c;可以根据鼠标指定的位置识别当前位置的颜色 项目功能包含&#xff1a; 鼠标按下实时采集鼠标处的颜色。 实时显示颜色值。 支持16进制格式和rgb格式。 实时显示预览颜色。 根据背景色自动计算合适的前景色…

国内好用的chatGPT和AI绘图工具

分享一个比较好用的AI 分享一个比较好用的AI&#xff0c;只是需要开通会员&#xff0c;目前官网的价格是&#xff1a;298&#xff0c;开通之后可以使用chatgpt4、AI绘画、图片融合等等&#xff01;不开通的话是可以免费使用15次的&#xff0c;下面是一些介绍图片&#xff01;链…

安全团队需要重点演练的四大威胁

文章目录 前言一、勒索软件攻击二、第三方风险三、内部威胁四、分布式拒绝服务攻击(DDoS)前言 桌面演练(推演)是一种重要的安全演习形式,参演人员利用演练方案、流程图、计算机模拟、视频会议等辅助手段,针对事先假定的演练情景,讨论和推演应急决策及现场处置,从而促使相…

点点数据K参数加密逆向分析(RPC方案跟加密算法还原)

文章目录 1. 写在前面2. 接口分析3. 断点分析4. RPC调用5. 算法还原 【&#x1f3e0;作者主页】&#xff1a;吴秋霖 【&#x1f4bc;作者介绍】&#xff1a;擅长爬虫与JS加密逆向分析&#xff01;Python领域优质创作者、CSDN博客专家、阿里云博客专家、华为云享专家。一路走来长…

蓝桥杯物联网竞赛_STM32L071_13_定时器

CubeMx配置LPTIM: counts internal clock events 计数内部时钟事件 prescaler 预分频器 updata end of period 更新期末 kil5配置&#xff1a; 中断回调函数完善一下&#xff1a; void HAL_LPTIM_AutoReloadMatchCallback(LPTIM_HandleTypeDef *hlptim){if(cnt ! 10) cnt…

用Python实现办公自动化(自动化处理Excel工作簿)

自动化处理Excel工作簿 &#xff08;一&#xff09;批量生产产品出货清单 以“出货统计表”为例&#xff0c; 需求&#xff1a;将出货记录按照出货日期分类整理成多张出货清单 “出货统计表数据案例” “产品出货清单模板” 1.提取出货统计表的数据 “Python程序代码” # 使用…