施磊老师基于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;
}

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

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

相关文章

4.18---缓存相关问题(操作原子性,击穿,穿透,雪崩,redis优势)

为什么要用redis做一层缓存&#xff0c;相比直接查mysql有什么优势&#xff1f; 首先介绍Mysql自带缓存机制的问题&#xff1a; MySQL 的缓存机制存在一些限制和问题,它自身带的缓存功能Query Cache只能缓存完全相同的查询语句&#xff0c;对于稍有不同的查询语句&#xff0c…

健康养生指南

在快节奏的现代生活中&#xff0c;健康养生成为人们关注的焦点。它不仅关乎身体的强健&#xff0c;更是提升生活质量、预防疾病的关键。掌握科学的养生方法&#xff0c;能让我们在岁月流转中始终保持活力。 饮食是健康养生的基础。遵循 “均衡膳食” 原则&#xff0c;每日饮食需…

#去除知乎中“盐选”付费故事

添加油猴脚本&#xff0c;去除知乎中“盐选”付费故事 // UserScript // name 盐选内容隐藏脚本 // namespace http://tampermonkey.net/ // version 0.2 // description 自动隐藏含有“盐选专栏”或“盐选”文字的回答卡片 // author YourName // mat…

如何防止接口被刷

目录 &#x1f6e1;️ 一、常见的防刷策略分类 &#x1f527; 二、技术实现细节 ✅ 1. 基于 IP 限流 ✅ 2. 给接口加验证码 ✅ 3. 使用 Token 限制接口访问权限 ✅ 4. 给接口加冷却时间&#xff08;验证码类经典&#xff09; ✅ 5. 使用滑动窗口限流算法&#xff08;更精…

github 项目迁移到 gitee

1. 查看远程仓库地址 git remote -v 2. 修改远程仓库地址 确保 origin 指向你的 Gitee 仓库&#xff0c;如果不是&#xff0c;修改远程地址。 git remote set-url origin https://gitee.com/***/project.git 3. 查看本地分支 git branch 4. 推送所有本地分支 git p…

探索大语言模型(LLM):目标、原理、挑战与解决方案

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言语言模型的目标语言模型的数学表示语言模型面临的挑战解决参数量巨大的方法1. 马尔可夫假设2. 神经网络语言模型3.自监督学习4. 分布式表示 脑图总结 前言 在自…

Kubernetes》》k8s》》Namespace

Namespace 概述 Namespace&#xff08;命名空间&#xff09; 是 Kubernetes 中用于逻辑隔离集群资源的机制&#xff0c;可将同一集群划分为多个虚拟环境&#xff0c;适用于多团队、多项目或多环境&#xff08;如开发、测试、生产&#xff09;的场景。 核心作用&#xff1a; 资…

FFUF指南

ffuf 的核心功能&#xff1a; 目录/文件发现&#xff1a; 通过暴力破解&#xff08;使用字典&#xff09;探测目标网站的隐藏目录或文件&#xff0c;例如&#xff1a; ffuf -w /path/to/wordlist.txt -u http://target.com/FUZZ 子域名枚举&#xff1a; 通过模糊测试发现目标…

Qt通过ODBC和QPSQL两种方式连接PostgreSQL或PolarDB PostgreSQL版

一、概述 以下主要在Windows下验证连接PolarDB PostgreSQL版&#xff08;阿里云兼容 PostgreSQL的PolarDB版本&#xff09;。Linux下类似&#xff0c;ODBC方式则需要配置odbcinst.ini和odbc.ini。 二、代码 以下为完整代码&#xff0c;包含两种方式连接数据库&#xff0c;并…

为什么浮点数会搞出Infinity和NAN两种类型?浮点数的底层原理?IEEE 754标准揭秘?

目录 什么是NAN? 不同编程语言的NaN 为什么浮点数会搞出Infinity和NAN两种类型? 浮点数 小数点位置浮动的原因 浮点数和整数 浮点数指令 精确性 浮点数的类型 为什么叫浮点数? 小数点位置浮动的原因 IEEE 754起源于intel公司 IEEE 754标准 编程语言的浮点数都…

Node.js Session 原理简单介绍 + 示例代码

目录 ✅ Session 原理简要说明 &#x1f9e9; 示例项目 - 使用 Node.js Express 实现简单 Session 登录 &#x1f4c1; 文件结构 &#x1f539; server.js (JavaScript) &#x1f538; index.html (HTML) ▶️ 程序运行步骤 ✅ 程序运行效果 &#x1f3af; 总结 在 We…

实战交易策略 篇十六:猎豹阿杜打板交易策略

文章目录 系列文章狙击涨停板的十大要诀炒股大成者,必具“三商”系列文章 实战交易策略 篇一:奥利弗瓦莱士短线交易策略 实战交易策略 篇二:杰西利弗莫尔股票大作手操盘术策略 实战交易策略 篇三:333交易策略 实战交易策略 篇四:价值投资交易策略 实战交易策略 篇五:底部…

Opentelemetry 项目解读

Opentelemetry 解读 1. 什么是 Opentelmetry Ot 统一了可观测的三个重要维度&#xff1a;分别是 Trace&#xff0c;Log&#xff0c;Metrics。 在没有 ot 之前&#xff0c;不同维度的可观测组件都是不同的&#xff1a; 在 Trace 领域&#xff1a;skywalking 一直很受欢迎&am…

与终端同居日记:Linux指令の进阶撩拨手册

前情提要&#xff1a; 当你和终端的关系从「早安打卡」进阶到「深夜代码同居」&#xff0c;那些曾经高冷的指令开始展露致命の反差萌—— man 是那个永远在线的钢铁直男说明书&#xff0c;只会说&#xff1a;"想懂我&#xff1f;自己看文档&#xff01;"&#xff08…

Java 开发玩转 MCP:从 Claude 自动化到 Spring AI Alibaba 生态整合

摘要 本文以原理与示例结合的形式讲解 Java 开发者如何基于 Spring AI Alibaba 框架玩转 MCP&#xff0c;主要包含以下内容。 1. 一些 MCP 基础与快速体验&#xff08;熟悉的读者可以跳过此部分&#xff09; 2. 如何将自己开发的 Spring 应用发布为 MCP Server&#xff0c;验…

【面试向】欠拟合和过拟合、正则化(Regularization)

训练集、验证集和测试集泛化误差过拟合&#xff08;Overfitting&#xff09;和 欠拟合&#xff08;Underfitting&#xff09;如何区分过拟合和欠拟合&#xff1f;欠拟合 —— 在训练集和验证集上都表现很差过拟合 —— 在训练集上表现很好&#xff0c;但在验证集或测试集上表现…

ClawCloud的免费空间(github用户登录可以获得$5元/月的免费额度)

免费的空间 Welcome to ClawCloud Lets create your workspace 官网&#xff1a;ClawCloud | Cloud Infrastructure And Platform for Developers 区域选择新加坡 然后这个页面会变成新加坡区域&#xff0c;再按一次确定&#xff0c;就创建好了工作台。 初始界面&#xff0…

Spring Boot + Caffeine:打造高性能缓存解决方案

1. 引言 1.1 缓存的重要性 缓存是提升系统性能的关键技术之一,通过将频繁访问的数据存储在内存中,减少对数据库或其他外部系统的访问次数,从而降低延迟并提高吞吐量。 缓存的基本概念:缓存是一种临时存储机制,用于快速访问常用数据。缓存在提升系统性能中的作用:减少数…

每天学一个 Linux 命令(24):chattr

​​可访问网站查看,视觉品味拉满: http://www.616vip.cn/24/index.html 每天学一个 Linux 命令(24):chattr 命令简介 chattr(Change Attribute)用于修改文件或目录的底层属性(如防删除、防修改),这些属性比普通权限更严格。常用于保护重要文件或优化文件系统行为。…

【java 13天进阶Day04】常用API、正则表达式,泛型、Collection集合API

Math类的使用。 Math用于做数学运算。Math类中的方法全部是静态方法&#xff0c;直接用类名调用即可。方法&#xff1a; public static int abs(int a) 获取参数a的绝对值public static double ceil(double a) 向上取整public static double floor(double a) 向下取整public s…