集群聊天项目整体梳理-注册业务

遇到了一点问题都一一解决了
1.vscode远程连接死活连不上,最后我把他给卸了,但是注意这里一定要把他卸干净,相应的方法网上一大堆,卸干净以后才连上linux
2.运行程序的过程中我发现数据库有点问题,但连接数据库时也是连接不上(密码是对的)后来看了这个博客才解决,博客找不到了,用的是这个命令***mysqladmin -uroot -p旧密码 password 新密码***
3.数据库修改表名;alter table old_name rename to new_name;

项目大概的流程

1.将每一个文件放在指定的目录下,这里要建立各个用途不一的目录

1.bin:放编译完成后的可执行文件
2.build:放CMake编译产生的中间文件
3.include:项目中的头文件
4.src:放源文件
5.thirdparty:放第三方库文件(这里是json.hpp)

2.CMake文件的生成

使用CMake前要在linux上安装CMake
CMake是一个跨平台的安装(编译)工具,可以用简单的语句来描述所有平台的安装(编译过程)

项目根目录下的CMakeLists.txt

cmake_minimum_required(VERSION 3.0)
project(chat)

# 配置编译选项
set(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} -g)

# 配置最终的可执行文件输出的路径
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)

# 配置头文件的搜索路径
include_directories(${PROJECT_SOURCE_DIR}/include)
include_directories(${PROJECT_SOURCE_DIR}/include/server)
include_directories(${PROJECT_SOURCE_DIR}/include/server/db)
include_directories(${PROJECT_SOURCE_DIR}/include/server/model)
include_directories(${PROJECT_SOURCE_DIR}/include/server/redis)
include_directories(${PROJECT_SOURCE_DIR}/thirdparty)

# 加载子目录
add_subdirectory(src)

src目录下的CMakeLists.txt文件

add_subdirectory(server)
add_subdirectory(client)

src/server下的CMakeLists.txt文件

# 定义了一个SRC_LIST变量,包含了该目录下所有的源文件
aux_source_directory(. SRC_LIST)
aux_source_directory(./db DB_LIST)
aux_source_directory(./model MODEL_LIST)
aux_source_directory(./redis REDIS_LIST)

# 指定生成可执行文件
add_executable(ChatServer ${SRC_LIST} ${DB_LIST} ${MODEL_LIST} ${REDIS_LIST})
# 指定可执行文件链接时需要依赖的库文件
target_link_libraries(ChatServer muduo_net muduo_base mysqlclient hiredis pthread)

/src/client下的CMakeLists.txt文件

# 定义了一个SRC_LIST变量,包含了该目录下所有的源文件
aux_source_directory(. SRC_LIST)

# 指定生成可执行文件
add_executable(ChatClient ${SRC_LIST})
# 指定可执行文件链接时需要依赖的库文件
target_link_libraries(ChatClient pthread)

3.客户端与服务器建立连接

此项目是基于muduo网络库开发的,muduo库的介绍就是:一个基于reactor反应堆模型的多线程C++网络库,网络模块几乎都交给了muduo来实现,这里讲一讲muduo的安装。
安装muduo的地址,muduo是基于boost开发的,所以还要安装boost
关于muduo网络库的使用可以看这里
我项目里网络模块完全交给了muduo,然后就只关注业务模块的代码。

4.数据库各个表的建立

  1. 用户表user:保存用户的id,name,password,state
    id:主键,用来识别用户身份
    name:非空且唯一
    password:密码,非空
    state:ENUM(‘online’,‘offline’)状态默认offline

  2. friend表:通过id来识别朋友属性,
    userid:用户id,与好友id组成联合主键
    friendid:好友id

5.利用json来序列化和反序列化

Json是一种轻量级的数据交换格式(也叫数据序列化方式)。Json采用完全独立于编程语言的文本格式
来存储和表示数据。简洁和清晰的层次结构使得 Json 成为理想的数据交换语言。 易于人阅读和编
写,同时也易于机器解析和生成,并有效地提升网络传输效率。
关于什么是序列化和为什么要序列化看这里

5.客户端通过服务器在数据库上注册业务

  • 如果注册成功会在用户表上添加一个用户信息
    客户端连接成功后,向服务器端发送一个序列化json对象,json里包含了msgid,name和password,服务器接收到以后进行反序列化,因为在业务类的私有成员里有一个存储函数的map表,然后根据msgid处理相应的业务(这里是注册业务),在服务器类通过函数对象接收msgid对应的函数,没找到的话会返回一个自定义函数(提示错误信息),然后将参数传入函数完成注册业务。
  • 注册业务会和数据库进行交互,在/include/server/model下有着负责和数据库交互的各种头文件,每个头文件里是各个表相关的类。
    这里有一个user.hpp
    user类里存储一个用户的基本信息,以及修改和获取信息的方法。
  • UserModel.hpp是有一个UserModel类,这是一个User表的数据操作类(可以直接修改数据库中信息)
// User表的增加方法
bool insert(User &user);

// 根据用户号码查询用户信息
User query(int id);

// 更新用户的状态信息
bool updateState(User user);

// 重置用户的状态信息
void resetState();

用MySQL可以生产一个mysql对象,通过mysql对象可以和MySQL进行交互。

  • 在/include/server/dp.hpp中有一个MySQL类,这是一个和数据库进行信息交互的类。
#ifndef DB_H
#define DB_H

#include <mysql/mysql.h>
#include <string>
using namespace std;

// 数据库操作类
class MySQL
{
public:
    // 初始化数据库连接
    MySQL();
    // 释放数据库连接资源
    ~MySQL();
    // 连接数据库
    bool connect();
    // 更新操作
    bool update(string sql);
    // 查询操作
    MYSQL_RES *query(string sql);
    // 获取连接
    MYSQL* getConnection();
private:
    MYSQL *_conn;
};

#endif

在#include <mysql/mysql.h>这个头文件里提供了操作数据库的方法。
1.连接数据库的方法

// 连接数据库
bool MySQL::connect()
{
    MYSQL *p = mysql_real_connect(_conn, server.c_str(), user.c_str(),
                                  password.c_str(), dbname.c_str(), 3306, nullptr, 0);
    if (p != nullptr)
    {
        // C和C++代码默认的编码字符是ASCII,如果不设置,从MySQL上拉下来的中文显示?
        mysql_query(_conn, "set names gbk");
        LOG_INFO << "connect mysql success!";
    }
    else
    {
        LOG_INFO << "connect mysql fail!";
    }

    return p;
}

2.初始化数据库和断开连接

// 初始化数据库连接
MySQL::MySQL()
{
    _conn = mysql_init(nullptr);
}

// 释放数据库连接资源
MySQL::~MySQL()
{
    if (_conn != nullptr)
        mysql_close(_conn);
}

3.更新操作

// 更新操作
bool MySQL::update(string sql)
{
    if (mysql_query(_conn, sql.c_str()))
    {
        LOG_INFO << __FILE__ << ":" << __LINE__ << ":"
                 << sql << "更新失败!";
        return false;
    }

    return true;
}

4.查询操作

// 查询操作
MYSQL_RES *MySQL::query(string sql)
{
    if (mysql_query(_conn, sql.c_str()))
    {
        LOG_INFO << __FILE__ << ":" << __LINE__ << ":"
                 << sql << "查询失败!";
        return nullptr;
    }
    
    return mysql_use_result(_conn);
}

5.获取连接

// 获取连接
MYSQL* MySQL::getConnection()
{
    return _conn;
}

有了这些方法,就可以在UserModel中封装对user的insert函数了

// 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;
    if (mysql.connect())
    {
        if (mysql.update(sql))
        {
            // 获取插入成功的用户数据生成的主键id
            user.setId(mysql_insert_id(mysql.getConnection()));
            return true;
        }
    }

    return false;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值