云计算百科
云计算领域专业知识百科平台

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

文章目录

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

Cmake简单介绍

Cmake与Makefile

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

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

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

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

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

    在这里插入图片描述

  • CmakeLists.txt 编写

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

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

    set(变量名 值) # 定义普通变量

  • 在 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})

  • 在 CMake 中,target_link_libraries 是一个关键命令,用于为指定的目标(可执行文件或库)链接依赖库。它管理目标的所有链接依赖关系,是现代 CMake 推荐的做法。 — 更多使用, 多见多总结 — 老师pdf也有很多, 多看

    target_link_libraries(<目标名称>
    <PRIVATE|PUBLIC|INTERFACE> <库1> [<库2>…]
    [<PRIVATE|PUBLIC|INTERFACE> <库3>…]
    )

  • aux_source_directory 是 CMake 中一个 用于自动收集源文件 的命令,但现代 CMake 已不再推荐使用它。

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

    为什么不推荐使用?

  • 不会自动检测新增文件 需要手动重新运行 CMake 才能识别新添加的源文件。
  • 包含无关文件风险 可能意外包含测试文件、备份文件(如 main.cpp.bak)。
  • 破坏构建系统的确定性 隐式文件收集会导致构建行为不可预测。
  • 与现代 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.txt CMake的主配置文件
    autobuild.sh 自动化构建脚本
  • 在 CMake 中,EXECUTABLE_OUTPUT_PATH 是一个用于设置可执行文件输出路径的全局变量。它控制通过 add_executable() 生成的可执行文件的存放位置。

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

    set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)

  • 建立 build 文件, 进入build 进行 cmake .., 之前的 杂乱的文件夹就在这个目录里了, 并且 可执行文件 在bin目录里

  • 完整如下:

    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简单使用

  • 创建数据库:

    CREATE DATABASE database_name; // 大小写都行

  • 选择要操作的 数据库:

    use database_name;

  • 查看默认的字符编码:

    show variables like "char%";

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

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

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

    User表

    字段名称字段类型字段说明约束
    id INT 用户id PRIMARY KEY, AUTO_INCREMENT
    name VARCHAR(50) 用户名 NOT NULL, UNIQUE
    password VARCHAR(50) 用户密码 NOT NULL
    state ENUM(‘online’,‘offline’) 当前登录状态 DEFAULT ‘offline’

    Friend表

    字段名称字段类型字段说明约束
    userid INT 用户id NOT NULL, 联合主键
    friendid INT 好友id NOT NULL, 联合主键

    AllGroup表

    字段名称字段类型字段说明约束
    id INT 组id PRIMARY KEY, AUTO_INCREMENT
    groupname VARCHAR(50) 组名称 NOT NULL, UNIQUE
    groupdesc VARCHAR(200) 组功能描述 DEFAULT ‘’

    GroupUser表

    字段名称字段类型字段说明约束
    groupid INT 组id NOT NULL, 联合主键
    userid INT 组员id NOT NULL, 联合主键
    grouprole ENUM(‘creator’,‘normal’) 组内角色 DEFAULT ‘normal’

    OfflineMessage表

    字段名称字段类型字段说明约束
    userid INT 用户id NOT NULL
    message VARCHAR(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;
    }

    赞(0)
    未经允许不得转载:网硕互联帮助中心 » 施磊老师基于muduo网络库的集群聊天服务器(二)
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!