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

施磊老师基于muduo网络库的集群聊天服务器(二)

文章目录

  • Cmake简单介绍
    • Cmake与Makefile
    • Cmake配置
    • CmakeLists.txt 编写
    • 完整cmake例子
    • 文件夹杂乱问题
    • 多级目录Cmake
    • vscode 极其推荐 的 cmake方式
  • Mysql环境与编程
    • mysql简单使用
    • User表
    • Friend表
    • AllGroup表
    • GroupUser表
    • OfflineMessage表
  • 集群聊天项目工程目录创建
  • 网络模块代码Chatserver
    • 头文件
    • 类函数定义文件
    • 主函数文件

Cmake简单介绍

Cmake与Makefile

Makefile 在大项目里, 很难写 出来, 推荐Cmake

  1. Makefile
    • 直接构建工具:定义编译规则(如 gcc -o main main.c),由 make 直接执行。
    • 手动编写:需指定每个文件的依赖和命令,适合小型项目。
    • 平台差异:不同系统的 make 可能有兼容性问题。
  2. CMake
    • 构建系统生成器:通过 CMakeLists.txt 描述项目结构,自动生成平台相关的构建文件(如 Makefile 或 IDE 工程)。
    • 跨平台:一套配置适配多平台(Linux/Mac/Windows)。
    • 高级功能:自动处理依赖、安装规则等,适合中大型项目。

Cmake配置

直接手写 cmake配置文件CMakeLists.txt, 命令行执行, 是可行的

vscode的cmake插件, 再写 cmake 时 会有代码提示----------> cmake 与 cmake tools

  1. cmake tools 设置里, 在对应的 本机或者 远程 设置一下 cmake 的 build enviroment: 添加一下 cmake的 路径(需要安装 cmake)

    在这里插入图片描述

CmakeLists.txt 编写

  1. CMAKE_CXX_FLAGS 是 CMake 中用于设置 全局 C++ 编译器选项 的变量,影响项目中所有 C++ 目标的编译行为。

  2. 在 CMake 中,set() 命令用于 定义或修改变量,是 CMake 脚本中最基础且重要的命令之一

    set(变量名 值)  # 定义普通变量
    
  3. 在 CMake 中,add_executable 是一个核心命令,用于定义可执行文件目标

    add_executable(<目标名称> [WIN32] [MACOSX_BUNDLE] [EXCLUDE_FROM_ALL] <源文件列表>)
    

    最主要的是 目标名称 和 源文件列表

    例子:

    #单文件
    add_executable(hello_world main.cpp)#多文件
    add_executable(my_app main.cpp utils.cpp include/utils.h
    )#条件编译--不同平台
    if(WIN32)add_executable(my_win_app WIN32 win_main.cpp)
    else()add_executable(my_win_app main_unix.cpp)
    endif()#使用变量组织源文件
    set(APP_SOURCES src/main.cpp src/core.cpp
    )
    add_executable(my_app ${APP_SOURCES})
    
  4. 在 CMake 中,target_link_libraries 是一个关键命令,用于为指定的目标(可执行文件或库)链接依赖库。它管理目标的所有链接依赖关系,是现代 CMake 推荐的做法。 — 更多使用, 多见多总结 — 老师pdf也有很多, 多看

    target_link_libraries(<目标名称><PRIVATE|PUBLIC|INTERFACE> <库1> [<库2>...][<PRIVATE|PUBLIC|INTERFACE> <库3>...]
    )
    
  5. aux_source_directory 是 CMake 中一个 用于自动收集源文件 的命令,但现代 CMake 已不再推荐使用它。

    aux_source_directory(<目录路径> <变量名>)
    

    为什么不推荐使用?

    1. 不会自动检测新增文件
      需要手动重新运行 CMake 才能识别新添加的源文件。
    2. 包含无关文件风险
      可能意外包含测试文件、备份文件(如 main.cpp.bak)。
    3. 破坏构建系统的确定性
      隐式文件收集会导致构建行为不可预测。
    4. 与现代 CMake 理念冲突
      现代 CMake 强调显式声明源文件(target_sources())。

    推荐使用 set 手动, 很麻烦

完整cmake例子

cmake_minimum_required(VERSION 3.0)
project(main) #工程名# 配置编译选项
set(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} -g)# 配置头文件搜索路径
include_directories()
# 配置库文件搜索路径
link_directories()#设置需要编译的 源文件列表
set(SRC_LIST ./nuduo_server.cpp)#把 . 指定路径下的 所有源文件名字 放入变量名--不用手动一个个输入
# aux_source_directory(. SRC_LIST) #暂时不用#生成可执行文件
add_executable(server ${SRC_LIST})# 表示server 这个目标程序 需要链接的 库
target_link_libraries(server muduo_net muduo_base pthread)

然后 先执行 cmake .----> 得到 makefile文件 —> 再make 即可

文件夹杂乱问题

直接 使用上面的 构建, 生成许多杂乱的 文件夹

一般 开源性代码 会有以下结构:

目录/文件用途描述文件类型示例
bin/存放生成的可执行文件(二进制文件)myapp, myapp.exe
lib/存放编译生成的库文件libmylib.a, mylib.so
include/存放项目的公共头文件utils.h, config.hpp
src/存放项目的主要源代码文件main.cpp, module.c
build/存放CMake生成的构建文件Makefile, build.ninja
example/存放示例代码或测试用例demo.cpp, test_case.py
thirdparty/存放第三方依赖库或源码googletest/, boost/
CMakeLists.txtCMake的主配置文件-
autobuild.sh自动化构建脚本-
  1. 在 CMake 中,EXECUTABLE_OUTPUT_PATH 是一个用于设置可执行文件输出路径的全局变量。它控制通过 add_executable() 生成的可执行文件的存放位置。

    在 CMake 中,PROJECT_SOURCE_DIR 是一个预定义变量,表示当前项目的根目录路径(即包含顶层 CMakeLists.txt 的目录)。

    set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
    
  2. 建立 build 文件, 进入build 进行 cmake .., 之前的 杂乱的文件夹就在这个目录里了, 并且 可执行文件 在bin目录里

  3. 完整如下:

    cmake_minimum_required(VERSION 3.0)
    project(main) #工程名# 配置编译选项
    set(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} -g)# 配置头文件搜索路径
    include_directories()
    # 配置库文件搜索路径
    link_directories()#设置需要编译的 源文件列表
    set(SRC_LIST ./nuduo_server.cpp)# 设置可执行文件最终目录
    set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)# 设置库文件最终目录
    set(LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/lib)#把 . 指定路径下的 所有源文件名字 放入变量名--不用手动一个个输入
    # aux_source_directory(. SRC_LIST) #暂时不用#生成可执行文件
    add_executable(server ${SRC_LIST})# 表示server 这个目标程序 需要链接的 库
    target_link_libraries(server muduo_net muduo_base pthread)

多级目录Cmake

内部的CMakeLists.txt 不需要 前5行, 这是 cmake的 入口
把这5行 放入 最外部的 CMakeLists.txt, 并且 加入 指定搜索的 子目录 即可

cmake_minimum_required(VERSION 3.0)
project(main) #工程名# 配置编译选项
set(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} -g)# 指定搜索的 子目录
add_subdirectory(testmuduo)

vscode 极其推荐 的 cmake方式

vscode 插件 会有图标, 使用这个 进行 编译------> 即完成, 并会 外部 自动构建 build 文件

在这里插入图片描述

注意: 仅会自动构建 build 文件, bin 文件 还需要手动指定, 在 内部CMakeLists.txt 里 进行

VS Code CMake 插件的自动化机制

(1) 自动行为说明

  • 自动生成 build/ 目录
    插件默认会在项目根目录下创建 build/(或用户配置的路径),自动处理以下内容:

    mkdir -p build && cd build
    cmake .. -DCMAKE_BUILD_TYPE=Debug  # 自动选择编译器工具链
    
  • 实时更新
    插件会监控 CMakeLists.txt 和源码文件的修改,但不会实时构建,仅在以下情况触发:

    • 手动点击编译按钮
    • 保存文件时(若开启 "cmake.configureOnEdit": true
    • 执行调试/运行任务时

(2) 优势

  • 无需手动输入 CMake 命令
  • 自动匹配编译器工具链(通过 CMake: Scan for Kits
  • 与 VS Code 调试功能深度集成

Cmake 到此为止-----> 更多内容 见 pdf

Mysql环境与编程

登录 之前写过, 略

mysql 有课程, 建议看一下 — > 必须要了解 数据库 mysql !!!

mysql简单使用

  1. 创建数据库:

    CREATE DATABASE database_name;   // 大小写都行
    
  2. 选择要操作的 数据库:

    use database_name; 
    
  3. 查看默认的字符编码:

    show variables like "char%";
    

    修改表的字符编码:alter table user default character set utf8;
    修改属性的字符编码:alter table user modify column name varchar(50) character set utf8;

  4. 从已有的 sql文件读取, 需要先创建 一个数据库, 并且选中它进行操作, 再 source ./<..>.sql

  5. 根据表, 在mysql里 进行创建. — 具体表

    User表

    字段名称字段类型字段说明约束
    idINT用户idPRIMARY KEY, AUTO_INCREMENT
    nameVARCHAR(50)用户名NOT NULL, UNIQUE
    passwordVARCHAR(50)用户密码NOT NULL
    stateENUM(‘online’,‘offline’)当前登录状态DEFAULT ‘offline’

    Friend表

    字段名称字段类型字段说明约束
    useridINT用户idNOT NULL, 联合主键
    friendidINT好友idNOT NULL, 联合主键

    AllGroup表

    字段名称字段类型字段说明约束
    idINT组idPRIMARY KEY, AUTO_INCREMENT
    groupnameVARCHAR(50)组名称NOT NULL, UNIQUE
    groupdescVARCHAR(200)组功能描述DEFAULT ‘’

    GroupUser表

    字段名称字段类型字段说明约束
    groupidINT组idNOT NULL, 联合主键
    useridINT组员idNOT NULL, 联合主键
    grouproleENUM(‘creator’,‘normal’)组内角色DEFAULT ‘normal’

    OfflineMessage表

    字段名称字段类型字段说明约束
    useridINT用户idNOT NULL
    messageVARCHAR(500)离线消息(存储Json字符串)NOT NULL

集群聊天项目工程目录创建

略—> bin build include src thirdparty 文件夹

外层 CMakeLists.txt 和 src 的两层 CMakeLists.txt

cmake_minimum_required(VERSION 3.0)
project(main) #工程名# 配置编译选项
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)# 加载子目录  src   既然进去, 就有 CMakeLists.txt
add_subdirectory(src)
# 加载子目录  src   既然进去, 就有 CMakeLists.txt
add_subdirectory(server)
# 所有源文件
aux_source_directory(. SRC_LIST)
# 生成可执行
add_executable(Chatserver ${SRC_LIST})# 链接库
target_link_libraries(Chatserver muduo_net muduo_base pthread)

网络模块代码Chatserver

hpp文件 写声明

源文件 进行定义使用

头文件

include/chatserver.hpp

#ifndef CHATSERVER_H
#define CHATSERVER_H#include <muduo/net/TcpServer.h>
#include <muduo/net/EventLoop.h>
using namespace muduo;
using namespace muduo::net;// 聊天服务器主类
class ChatServer
{
public:// 初始化聊天服务器对象ChatServer(EventLoop *loop,const InetAddress &listenAddr,const string &nameArg);// 启动服务void start();private:// 上报连接 相关信息的回调void onConnect();// 上报读写事件相关信息的 回调void onMessage();TcpServer _server; // 组合的muduo库, 实现服务器功能的 类对象EventLoop *_loop;  // 指向事件循环对象的 指针
};#endif 

类函数定义文件

src/server/chatserver.cpp

不完整, 回调内部 还没写

#include "chatserver.hpp"#include <functional>
using namespace std;
using namespace placeholders;// 类外 定义成员函数
ChatServer::ChatServer(EventLoop *loop,const InetAddress &listenAddr,const string &nameArg): _server(loop, listenAddr, nameArg), _loop(loop)
{// 注册连接回调函数_server.setConnectionCallback(std::bind(&ChatServer::onConnect, this, _1));// 注册消息回调_server.setMessageCallback(std::bind(&ChatServer::onMessage, this, _1, _2, _3));// 设置线程数_server.setThreadNum(4);
}void ChatServer::start()
{_server.start();
}void ChatServer::onConnect(const TcpConnectionPtr& conn)
{}void ChatServer::onMessage(const TcpConnectionPtr& conn,Buffer* buf,Timestamp time)
{   }

主函数文件

src/server/main.cpp

#include "chatserver.hpp"
#include <iostream>
using namespace std;int main()
{EventLoop loop;InetAddress addr("127.0.0.1", 6000);ChatServer server(&loop, addr, "ChatServer");server.start();loop.loop();return 0;
}

相关文章:

  • 大模型如何突破“知识盲区”?一场静悄悄的技术革命正在发生
  • Pytest 的配置和命令行选项:掌控你的测试执行 (Pytest 系列之七)
  • VirtualBox导入 .ova 文件出错,怎么解决
  • 【Linux学习笔记】进程调度与切换之O(1)调度算法
  • Oracle日志系统之重做日志和归档日志
  • 2025年03月中国电子学会青少年软件编程(Python)等级考试试卷(四级)答案 + 解析
  • Python项目调用Java数据接口实现CRUD操作
  • 什么是Python单例模式
  • Python 3.13 support for PyTorch
  • python中MongoDB 的两个驱动
  • 基于C++(MFC)图形编辑界面工具
  • 一个可以自定义Java服务名日志打印的小工具
  • CSS 文件格式
  • Ubuntu上安装Mysql
  • redis利用备忘录
  • 在 Vue 3 中将拆分后的数组合并回原数组
  • 云轴科技ZStack入选中国人工智能产业发展联盟《大模型应用交付供应商名录》
  • Muduo网络库实现 [十六] - HttpServer模块
  • 线上蓝桥杯比赛环境配置
  • C#中扩展方法和钩子机制使用
  • 人民日报头版开新栏:收官之年干劲满,决战决胜勇争先
  • 体坛联播|皇马补时绝杀毕尔巴鄂,利物浦最快下轮即可夺冠
  • 北京理工大学解除宫某聘用关系,该教授此前被指骚扰猥亵学生
  • 大悦城:去年净亏损29.77亿元,三年累计亏损超70亿元
  • 摩根大通首席执行官:贸易战损害美国信誉
  • 自然资源部:一季度存量商品房转移登记办理量同比增长超三成