施磊老师基于muduo网络库的集群聊天服务器(二)
文章目录
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;
}
相关文章:
施磊老师基于muduo网络库的集群聊天服务器(二)
文章目录 Cmake简单介绍Cmake与MakefileCmake配置CmakeLists.txt 编写完整cmake例子文件夹杂乱问题多级目录Cmakevscode 极其推荐 的 cmake方式 Mysql环境与编程mysql简单使用User表Friend表AllGroup表GroupUser表OfflineMessage表 集群聊天项目工程目录创建网络模块代码Chatse…...
Git拉分支技巧:从零开始创建并推送分支
Git拉分支技巧:从零开始创建并推送分支 在团队协作开发中,Git 分支管理是不可或缺的技能。合理地创建、同步和推送分支,不仅能提高开发效率,还能避免代码冲突。本文将基于以下技巧,详细讲解如何从零开始创建并推送一个…...
Kotlin实现Android应用保活方案
Kotlin实现Android应用保活优化方案 以下的Android应用保活实现方案,更加符合现代Android开发规范,同时平衡系统限制和用户体验。 1. 前台服务方案 class OptimizedForegroundService : Service() {private val notificationId 1private val channel…...
Mysql insert一条数据的详细过程
以下是MySQL在接收到INSERT语句后存储数据的详细过程解析,结合存储引擎(以InnoDB为例)和物理存储机制分步说明。 一、SQL解析与事务启动 1.语法解析 MySQL首先解析INSERT语句,验证字段是否存在、数据类型是否匹配、约束…...
线性DP:最长上升子序列(子序列可不连续,子数组必须连续)
目录 Q1:简单遍历 Q2:变式(加大数据量) Q1:简单遍历 Dp问题 状态表示 f(i,j) 集合所有以第i个数结尾的上升子序列集合-f(i,j)的值存的是什么序列长度最大值max- 状态计算 (其实质是集合的划分)…...
C语言之文本加密程序设计
🌟 嗨,我是LucianaiB! 🌍 总有人间一两风,填我十万八千梦。 🚀 路漫漫其修远兮,吾将上下而求索。 文本加密程序设计 摘要:本文设计了一种文本加密程序,旨在提高信息安…...
生成器模式深入解析与 Spring 源码应用
摘要 本文以生成器模式为研究对象,采用通俗易懂的表述方式,详细阐释其核心概念与运行机制。通过构建游戏角色创建、电商订单生成等实际 Java 案例,直观呈现该模式在复杂对象构建中的应用优势。同时,深入剖析 Spring 框架源码&…...
云效部署实现Java项目自动化部署图解
前言 记录下使用云效部署Java项目,实现java项目一键化自动化部署。 云效流程说明: 1.云效拉取最新git代码后 2.进行maven编译打包后,上传到指定服务器目录 3.通过shell脚本,先kill java项目后,通过java -jar 启动项…...
0801ajax_mock-网络ajax请求1-react-仿低代码平台项目
0 vite配置proxy代理 vite.config.ts代码如下图所示: import { defineConfig } from "vite"; import react from "vitejs/plugin-react";// https://vite.dev/config/ export default defineConfig({plugins: [react()],server: {proxy: {&qu…...
基于Python智能体API的Word自动化排版系统:从零构建全流程模块化工作流与版本控制研究
基于Python智能体API的Word自动化排版系统:从零构建全流程模块化工作流与版本控制实践研究 1. 引言2. 研究背景与意义3. 自动排版工作流的设计原理3.1 文档内容提取与解析3.2 样式参数与格式化规则3.3 智能体API接口调用3.4 自动生成与批量处理3.5 与生成式AI的协同4. 系统架构…...
Java【网络原理】(4)HTTP协议
目录 1.前言 2.正文 2.1自定义协议 2.2HTTP协议 2.2.1抓包工具 2.2.2请求响应格式 2.2.2.1URL 2.2.2.2urlencode 2.2.3认识方法 2.2.3.1GET与POST 2.2.3.2PUT与DELETE 2.2.4请求头关键属性 3.小结 1.前言 哈喽大家好啊,今天来继续给大家带来Java中网络…...
每天学一个 Linux 命令(27):head
可访问网站查看,视觉品味拉满: http://www.616vip.cn/27/index.html head 是 Linux 中用于查看文件开头部分内容的命令,默认显示文件前 10 行,适合快速预览文件结构或日志头部信息。 命令格式 head [选项] [文件]常用选项 选项说明-n <行数>指定显示前 N 行(如…...
【2025软考高级架构师】——计算机系统基础(7)
摘要 本文主要介绍了计算机系统的组成,包括硬件和软件两大部分。硬件由处理器、存储器、总线、接口和外部设备等组成,软件则涵盖系统软件和应用软件。文章还详细阐述了冯诺依曼计算机的组成结构,包括 CPU、主存储器、外存等,并解…...
自定义 strlen 函数:递归实现字符串长度计算
目录 自定义 strlen 函数:递归实现字符串长度计算 一.引言 二.代码呈现 三.代码结构与功能概述 1.自定义 my_strlen 函数 1.函数参数与功能 2.代码逻辑分析 1.参数有效性检查: 2.递归计算字符串长度: 2.main 函数 1.变量定义 2.函…...
LeetCode 打家劫舍+删除并获得点数
题目描述 打家劫舍题目传送门1 删除并获得点数传送门2 思路 这两道题看似毫无关系,但竟然可以用桶数组联系起来!! 先说打家劫舍这道题 限制条件是不能走相邻的屋,再联想到跳台阶(走一格或两格)&#x…...
图解MCP:Model Context Protocol
🧠 向所有学习者致敬! “学习不是装满一桶水,而是点燃一把火。” —— 叶芝 我的博客主页: https://lizheng.blog.csdn.net 🌐 欢迎点击加入AI人工智能社区! 🚀 让我们一起努力,共创…...
【网络】数据链路层知识梳理
全是通俗易懂的讲解,如果你本节之前的知识都掌握清楚,那就速速来看我的笔记吧~ 自己写自己的八股!让未来的自己看懂! (全文手敲,受益良多) 数据链路层 我们来重新理解一下这个图:…...
积木报表查询出现jdbc.SQLServerException: 对象名 ‘user_tab_comment 的解决方法
目录 前言1. 问题所示2. 解决方法前言 🤟 找工作,来万码优才:👉 #小程序://万码优才/r6rqmzDaXpYkJZF 爬虫神器,无代码爬取,就来:bright.cn 1. 问题所示 使用帆软报表无错,后续使用积木报表查询出错: 没有显示报表: 具体错误信息如下:...
数字孪生废气处理工艺流程
图扑数字孪生废气处理工艺流程系统。通过精准 3D 建模,对废气收集、预处理、净化、排放等全流程进行 1:1 数字化复刻,实时呈现设备运行参数、污染物浓度变化等关键数据。 借助图扑可视化界面,管理者可直观掌握废气处理各环节状态,…...
【某比特币网址请求头部sign签名】RSA加密逆向分析
目标:aHR0cDovL21lZ2FiaXQudmlwL21hcmtldA 直接搜索sign不方便定位,可以换个思路搜asi_uuid或者user_info 为什么搜这个,因为都是请求头里面的参数,基本上会在一起 实际上就是Object(h.a)((new Date).getTime()) 直接在这里打断点…...
基于WebRTC技术的EasyRTC:支持任意平台设备的实时音视频通信解决方案
一、技术架构与核心优势 EasyRTC是一套基于WebRTC技术的实时音视频通信框架,旨在为开发者提供高效、稳定、跨平台的通信解决方案。其核心优势在于支持任意平台设备,包括Web端、移动端、桌面端和嵌入式设备,真正实现“一次开发,多…...
DNS解析失败怎么解决?
在互联网时代,畅快地浏览网页、使用各类网络服务已成为生活常态。然而,当屏幕突然弹出 “DNS解析失败”的提示,原本顺畅的网络连接戛然而止,让人倍感困扰。DNS即域名系统,它如同互联网的 “电话簿”,负责将…...
2025年4月19日
1.英语 1.单词 2.翻译 老年人食堂 In recent years, elderly population in China has continued to grow. The Chinese government is taking various measures to advance the construction of the elderly care service system and to make the later lives of the elde…...
FastGPT安装前,系统环境准备工作?
1.启用适用于 Linux 的 Windows 子系统 方法一:打开控制面板 -> 程序 -> 启用或关闭Windows功能->勾选 “适用于Linux的Vindows子系统” 方法二:以管理员身份打开 PowerShell(“开始”菜单 >“PowerShell” >单击右键 >“…...
从零起步的Kaggle竞赛 - BirdCLEF2025
一个优秀的coder,先从CV工程开始...... 首先复制了 LB 0.804- EfficientNet B0 Pytorch Pipeline | Kaggle 这个notebook并尝试提交(Kaggle的notebook中包括参赛者训练好的模型,所以本次提交只能熟悉一下流程而已),ok…...
【Vue】组件通信(Props/Emit、EventBus、Provide/Inject)
个人主页:Guiat 归属专栏:Vue 文章目录 1. Props/Emit 父子组件通信1.1 Props 向下传递数据1.2 Emit 向上传递事件 2. EventBus 跨组件通信2.1 创建事件总线2.2 使用事件总线2.3 EventBus 优缺点 3. Provide/Inject 深层组件通信3.1 基本使用3.2 响应式处…...
electron打包是没有正确生成electron.exe,x ENOENT: no such file or directory, rename:
情况一 arch配置错误,最好根据自己的电脑架构配置 win: {target: [{target: "nsis", arch: ["x64"],},],artifactName: "${productName}_${version}.${ext}",}, 情况二、 electron没有被正确下载,可以翻墙重新通过npm…...
立体匹配模型RAFT-Stereo的onnx导出与trt使用指南
这里写目录标题 如何将 RAFT-Stereo 模型导出为 ONNX 格式转化为静态的模型:转化为动态的模型:reference通过将 RAFT-Stereo 模型转换为 ONNX 格式,我们能够在不同的推理引擎和硬件平台上高效地部署和运行该模型,而无需依赖原始的 PyTorch 环境。这为在实际应用中使用 RAFT…...
C++数组栈与链表栈
数组栈 #include <iostream> using namespace std; class mystack{ private:int dat[1000];int curr0; public:void push(int);void pop();int top();bool empyt();int size(); }; void mystack::push(int b){if(curr<1000){dat[curr]b;curr;} } void mystack::pop()…...
QT实现串口透传的功能
在一些产品的开发的时候,需要将一个串口的数据发送给另外一个串口进行转发。 具体的代码如下: #include "mainwindow.h" #include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::Ma…...
