当前位置: 首页 > news >正文

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

在前几节的研究中,我们已经实现网络层与业务层分离,本节实现数据层与业务层分离,降低各层之间的耦合性,同时实现用户注册业务。

网络层专注于处理网络通信与读写事件

业务层专注于处理读写事件到来时所需求的各项业务

数据层专注于与底层数据库间进行增删改查。

数据库中有User、Friend、AllGroup、GroupUser和OfflineMessage表,在model数据层中,要提供一些类与数据库中的表对应起来,以便于将数据库中读取到的字段信息也对象的方式提供给业务模块使用

项目流程如下:

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博客

一、User类

在include/server下创建model文件夹,在model文件夹下创建与用户表对应的、操作用户的User类,定义在头文件user.hpp中,由于代码体量较小,直接在头文件中进行实现

用户表user

#ifndef USER_H
#define USER_H#include <string>
using namespace std;//User表的ORM类
class User
{
public:User(int id = -1, string name = "", string pwd = "", string state = "offline"){this->id = id;this->name = name;this->password = pwd;this->state = state;}//设置 void setId(int id) { this->id = id; }void setName(string name) { this->name = name; }void setPwd(string pwd) { this->password = pwd; }void setState(string state) { this->state = state; }//获取 int getId() { return this->id; }string getName() { return this->name; }string getPwd() { return this->password; }string getState() { return this->state; }protected:int id;//ID号 string name;//姓名 string password;//密码 string state;//状态 
};#endif

二、UserModel类

UserModel为操纵数据库User表的类,主要实现增加用户、查询用户、更新用户、重置用户信息

在include/server/model文件创建usermodel.hpp

#ifndef USERMODEL_H
#define USERMODEL_H#include "user.hpp"//User表的数据操作类
class UserModel {
public://User表的增加方法bool insert(User &user);//根据用户号码查询用户信息User query(int id);//更新用户的状态信息bool updateState(User user);//重置用户的状态信息void resetState();
};#endif

src/server中创建model文件夹,创建usermodel.cpp对UserModel类中insert方法进行实现

#include "usermodel.hpp"
#include "db.hpp"
#include <iostream>
using namespace std;// User表的增加方法
bool UserModel::insert(User &user)
{// 1.组装sql语句char sql[1024] = {0};sprintf(sql, "insert into user(name, password, state) values('%s', '%s', '%s')",user.getName().c_str(), user.getPwd().c_str(), user.getState().c_str());MySQL mysql;         // 定义一个mysql对象if (mysql.connect()) // 连接成功了{if (mysql.update(sql)) // 更新这个sql语句传进去{// 获取插入成功的用户数据生成的主键iduser.setId(mysql_insert_id(mysql.getConnection())); // 拿到数据库生成的id作为用户的id号return true;}}return false;
}

其余方法在实现后续功能模块中进行实现

三、注册功能

本节来实现注册功能,判断是否能通过UserModel类顺利将用户信息插入数据库中。

在public.hpp中定义注册消息和注册响应消息

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

注:此时登录消息对应的msgid=1,注册消息对应的msgid=2

在第五节C++项目——集群聊天服务器项目(五)网络模块与业务模块-CSDN博客中,注册与登录信息仅仅为一个日志信息,此处将注册业务进行实现

chatservice.hpp中,定义用户操作类对象

#ifndef CHATSERVICE_H
#define CHATSERVICE_H#include <muduo/net/TcpConnection.h>
#include <unordered_map>//一个消息ID映射一个事件处理 
#include <functional>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);private:ChatService();//单例 //存储消息id和其对应的业务处理方法,消息处理器的一个表,写消息id对应的处理操作 unordered_map<int, MsgHandler> _msgHandlerMap;//数据操作类对象UserModel _userModel;};#endif

在chatservice.cpp中,编写注册业务函数

// 处理注册业务  name  password
void ChatService::reg(const TcpConnectionPtr &conn, json &js, Timestamp time)
{string name = js["name"];    // 获取名字string pwd = js["password"]; // 获取密码User user; // 创建用户对象user.setName(name);user.setPwd(pwd);bool state = _userModel.insert(user); // 新用户的插入if (state)                            // 插入成功{// 注册成功json response;response["msgid"] = REG_MSG_ACK;response["errno"] = 0;response["id"] = user.getId();conn->send(response.dump()); // 回调 ,返回json字符串}else // 插入失败{// 注册失败json response;response["msgid"] = REG_MSG_ACK;response["errno"] = 1;conn->send(response.dump()); // 回调 ,返回json字符串}
}

步骤:

(1)从json对象中获取姓名和密码

(2)实例化User对象,分别将姓名和密码传入,使用UserModel类进行新用户的插入

注:状态默认为不在线(实际上创建的时候用户确实不在线),id由数据库派发

(3)定义json对象,回调响应信息,error = 0代表创建成功,error = 1代表创建失败。

若创建成功,需额外将创建成功的用户id号返回,如果失败,直接将json序列化发送回客户端

四、功能实现

使用CMake编译成功后,执行我们的ChatServer服务器,开启监听客户端连接

客户端使用下述命令登录服务器

telnet 127.0.0.1 6000

密码:123456

服务端显示有一个新的连接接入

客户端输入

{"msgid":2,"name":"Jiao","password":"123456"}

创建成功,返回error=0,用户id号以及注册响应msgid,如图所示

客户端,显示mysql连接成功了

我们进底层数据库看一下,

新建用户成功,功能实现完毕!(其他用户为自行学习时创建的)

感兴趣的小伙伴一起来试一下吧~

如果有问题还请及时联系我哦,感谢~

相关文章:

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

在前几节的研究中&#xff0c;我们已经实现网络层与业务层分离&#xff0c;本节实现数据层与业务层分离&#xff0c;降低各层之间的耦合性&#xff0c;同时实现用户注册业务。 网络层专注于处理网络通信与读写事件 业务层专注于处理读写事件到来时所需求的各项业务 数据层专…...

VBA语言専攻介绍(20240331更新)

VBA语言専攻简介 “VBA语言専攻”是大家汲取知识的源泉&#xff0c;是提高自己能力的净土&#xff0c;正如我对平台的介绍&#xff1a;社会的进步&#xff0c;源于对知识的尊重和敬仰。希望每一位学员&#xff0c;每一位关注平台的朋友&#xff0c;都能很好的利用这个平台来学…...

Golang- 邮件服务,发送邮件

依赖 go get -u github.com/jordan-wright/email文档 文档 示例代码 邮箱的相关配置 # email configuration email:port: 25 # 端口要配置25 否则可能出现EOF错误from: xxx1qq.comhost: smtp.qq.comis-ssl: truesecret: xxxxxnickname: 大锦余发送邮件代码 package utili…...

C语言:编译和链接

前言 在ANSI C的任何一种实现中&#xff0c;存在两个不同的环境。 第1种是翻译环境&#xff0c;在这个环境中源代码被转换为可执行的机器指令&#xff08;二进制指令&#xff09;。第2种是执行环境&#xff0c;它用于实际执行代码。 目录 1.翻译环境1.1 预处理&#xff08;预编…...

JavaEE 初阶篇-深入了解多线程安全问题(出现线程不安全的原因与解决线程不安全的方法)

&#x1f525;博客主页&#xff1a; 【小扳_-CSDN博客】 ❤感谢大家点赞&#x1f44d;收藏⭐评论✍ 文章目录 1.0 多线程安全问题概述 1.1 线程不安全的实际例子 2.0 出现线程不安全的原因 2.1 线程在系统中是随机调度且抢占式执行的模式 2.2 多个线程同时修改同一个变量 2.3 线…...

计算机网络⑦ —— 网络层协议

1. ARP协议 在传输⼀个 IP 数据报的时候&#xff0c;确定了源 IP 地址和⽬标 IP 地址后&#xff0c;就会通过主机路由表确定 IP 数据包下⼀跳。然⽽&#xff0c;⽹络层的下⼀层是数据链路层&#xff0c;所以我们还要知道下⼀跳的 MAC 地址。由于主机的路由表中可以找到下⼀跳的…...

正弦实时数据库(SinRTDB)的使用(7)-历史统计查询

前文已经将正弦实时数据库的使用进行了介绍&#xff0c;需要了解的可以先看下面的博客&#xff1a; 正弦实时数据库(SinRTDB)的安装 正弦实时数据库(SinRTDB)的使用(1)-使用数据发生器写入数据 正弦实时数据库(SinRTDB)的使用(2)-接入OPC DA的数据 正弦实时数据库(SinRTDB)…...

编译和链接知识点

为什么我们在vs等编译器上写出的代码通过运行就会实现相关功能呢&#xff1f; 解决这个问题的关键就是关于编译与链接的知识。 首先从大的分类里有两部分&#xff1a;编译和链接 而编译这一大的部分又分为预处理&#xff08;也叫预编译&#xff09;&#xff0c;编译&#xf…...

大话设计模式之工厂模式

工厂模式&#xff08;Factory Pattern&#xff09;是一种创建型设计模式&#xff0c;它提供了一种创建对象的最佳方式&#xff0c;而无需指定将要创建的对象的确切类。通过使用工厂模式&#xff0c;我们可以将对象的创建和使用分离&#xff0c;从而使代码更具灵活性和可维护性。…...

Windows MySQL通过data 文件夹恢复数据

前言 在MySql数据库中,为了备份和恢复数据,通常会使用mysqldump工具来导出和导入数据。但是&#xff0c;如果数据库非常大&#xff0c;name导出和导入数据可能会需要很长时间。这时&#xff0c;一种更快速的备份和恢复数据的方式就是直接复制mysql的data文件夹。 什么是mysql的…...

ARP协议定义及工作原理

ARP的定义 地址解析协议(Address Resolution Protocol&#xff0c;ARP)&#xff1a;ARP协议可以将IPv4地址(一种逻辑地址)转换为各种网络所需的硬件地址(一种物理地址)。换句话说&#xff0c;所谓的地址解析的目标就是发现逻辑地址与物理地址的映射关系。 ARP仅用于IPv4协议&a…...

express实现用户登录和注册接口

目录 1 创建数据库2 连接数据库3 集成ORM库4 创建业务逻辑5 创建路由7 测试接口总结 我们在编写后端接口的时候操作数据库是一种常见的功能需求&#xff0c;express本身并不提供直接操作数据库的能力&#xff0c;需要借助第三方库来操作数据库&#xff0c;本篇讲解一下软件开发…...

数字化转型,效率增长才是王道

在当今商业世界&#xff0c;数字化已经成为推动企业增长的强大引擎。然而&#xff0c;值得注意的是&#xff0c;数字化并非只是简单地追求规模扩张&#xff0c;更重要的是实现降本增效。没有效率的增长&#xff0c;就像是在加速自我毁灭。在数字化转型的道路上&#xff0c;企业…...

RHCE-2-chrony服务器

简介 重要性 由于IT系统中&#xff0c;准确的计时非常重要&#xff0c;有很多种原因需要准确计时&#xff1a; 在网络传输中&#xff0c;数据包括和日志需要准确的时间戳 各种应用程序中&#xff0c;如订单信息&#xff0c;交易信息等 都需要准确的时间戳 Linux的两个时钟 硬…...

音频RK809

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 一、目的二、知识准备2.1Audio框架2.1.1 DAI2.1.2 CODEC2.1.3 machine三、原理图3.1 整体原理图3.2 喇叭部分3.3 麦克风部分四、设备树4.1 sound 部分4.2 codec 部分五、驱动讲...

解决 linux 服务器 java 命令不生效问题

在Linux系统中&#xff0c;当你安装Java并设置了JAVA_HOME环境变量后&#xff0c;你可能需要使用source /etc/profile命令来使Java命令生效。这是因为/etc/profile是一个系统级的配置文件&#xff0c;它包含了系统的全局环境变量设置。 但是需要注意的是&#xff0c;source /e…...

22 多态

目录 多态的概念多态的定义及实现抽象类多态的原理单继承和多继承关系中的虚函数表继承和多态常见的面试问题 前言 需要声明的&#xff0c;下面的代码和解释的哦朴实vs2013x86环境&#xff0c;涉及指针是4bytes&#xff0c;如果要其他平台下&#xff0c;部分代码需要改动。比…...

排序算法超详细代码和知识点整理(java版)

排序 1、冒泡排序 ​ 两层循环&#xff0c;相邻两个进行比较&#xff0c;大的推到后面去&#xff0c;一共比较“数组长度”轮&#xff0c;每一轮都是从第一个元素开始比较&#xff0c;每一轮比较都会将一个元素固定到数组最后的一个位置。【其实就是不停的把元素往后堆&#…...

Java复习第十二天学习笔记(JDBC),附有道云笔记链接

【有道云笔记】十二 3.28 JDBC https://note.youdao.com/s/HsgmqRMw 一、JDBC简介 面向接口编程 在JDBC里面Java这个公司只是提供了一套接口Connection、Statement、ResultSet&#xff0c;每个数据库厂商实现了这套接口&#xff0c;例如MySql公司实现了&#xff1a;MySql驱动…...

Python从零到一构建GPT模型

只用Python和 torch框架&#xff0c;从零到一构建GPT模型&#xff0c;对大语言模型入门&#xff0c;了解GPT的内部网络结构&#xff0c;是一个很好示例。 Build_GPT_from_Scratch.ipynb...

日语AI面试高效通关秘籍:专业解读与青柚面试智能助攻

在如今就业市场竞争日益激烈的背景下&#xff0c;越来越多的求职者将目光投向了日本及中日双语岗位。但是&#xff0c;一场日语面试往往让许多人感到步履维艰。你是否也曾因为面试官抛出的“刁钻问题”而心生畏惧&#xff1f;面对生疏的日语交流环境&#xff0c;即便提前恶补了…...

【JVM】- 内存结构

引言 JVM&#xff1a;Java Virtual Machine 定义&#xff1a;Java虚拟机&#xff0c;Java二进制字节码的运行环境好处&#xff1a; 一次编写&#xff0c;到处运行自动内存管理&#xff0c;垃圾回收的功能数组下标越界检查&#xff08;会抛异常&#xff0c;不会覆盖到其他代码…...

Python爬虫(二):爬虫完整流程

爬虫完整流程详解&#xff08;7大核心步骤实战技巧&#xff09; 一、爬虫完整工作流程 以下是爬虫开发的完整流程&#xff0c;我将结合具体技术点和实战经验展开说明&#xff1a; 1. 目标分析与前期准备 网站技术分析&#xff1a; 使用浏览器开发者工具&#xff08;F12&…...

相机从app启动流程

一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...

【HTML-16】深入理解HTML中的块元素与行内元素

HTML元素根据其显示特性可以分为两大类&#xff1a;块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...

UR 协作机器人「三剑客」:精密轻量担当(UR7e)、全能协作主力(UR12e)、重型任务专家(UR15)

UR协作机器人正以其卓越性能在现代制造业自动化中扮演重要角色。UR7e、UR12e和UR15通过创新技术和精准设计满足了不同行业的多样化需求。其中&#xff0c;UR15以其速度、精度及人工智能准备能力成为自动化领域的重要突破。UR7e和UR12e则在负载规格和市场定位上不断优化&#xf…...

力扣-35.搜索插入位置

题目描述 给定一个排序数组和一个目标值&#xff0c;在数组中找到目标值&#xff0c;并返回其索引。如果目标值不存在于数组中&#xff0c;返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 class Solution {public int searchInsert(int[] nums, …...

JVM 内存结构 详解

内存结构 运行时数据区&#xff1a; Java虚拟机在运行Java程序过程中管理的内存区域。 程序计数器&#xff1a; ​ 线程私有&#xff0c;程序控制流的指示器&#xff0c;分支、循环、跳转、异常处理、线程恢复等基础功能都依赖这个计数器完成。 ​ 每个线程都有一个程序计数…...

2025年渗透测试面试题总结-腾讯[实习]科恩实验室-安全工程师(题目+回答)

安全领域各种资源&#xff0c;学习文档&#xff0c;以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具&#xff0c;欢迎关注。 目录 腾讯[实习]科恩实验室-安全工程师 一、网络与协议 1. TCP三次握手 2. SYN扫描原理 3. HTTPS证书机制 二…...

LRU 缓存机制详解与实现(Java版) + 力扣解决

&#x1f4cc; LRU 缓存机制详解与实现&#xff08;Java版&#xff09; 一、&#x1f4d6; 问题背景 在日常开发中&#xff0c;我们经常会使用 缓存&#xff08;Cache&#xff09; 来提升性能。但由于内存有限&#xff0c;缓存不可能无限增长&#xff0c;于是需要策略决定&am…...