All notable changes to this project will be documented in this file.
核心变更: 修复了当用户没有任何私人题库时,前端无法正确渲染操作界面,导致“新建题库”功能失效的问题。问题根源在于 home.html 的 renderDecks() 函数在处理空题库列表时未正确初始化 UI 状态,现已修复以确保创建入口始终可用。
- resources/home.html
- 修正
renderDecks()渲染函数逻辑,当私人题库列表为空时,仍正确显示“新建题库”按钮和操作区域 - 避免因空数组导致的 DOM 更新异常或状态判断错误,保障用户首次使用时可顺利创建首个题库
- 修正
核心变更: 修复了删除题库(Deck)时未同步删除其所属卡片(Card)的问题,确保数据一致性。该问题源于 Deck::Delete() 方法未显式清理关联卡片,尽管数据库定义了 ON DELETE CASCADE,但在某些部署环境或连接配置下级联行为可能未生效。现通过在 Model 层主动删除卡片,双重保障数据完整性。
- src/app/models/Deck.cpp
- 重写
Delete(deck_id)方法,在删除题库前显式调用 SQL 删除所有deck_id匹配的卡片 - 使用事务包裹“删卡片 + 删题库”操作,确保原子性,防止中间状态导致数据残留
- 即使数据库外键级联生效,此逻辑也作为防御性编程增强系统鲁棒性
- 重写
核心变更: 完成从原型到生产级 Web 服务器的关键跃迁。通过引入路由表机制、修复并发死锁、杜绝资源泄露等关键改进,显著提升系统稳定性、可维护性与健壮性。服务器现已支持高并发请求、安全资源管理与清晰的 MVC 架构。
-
src/app/Router.h & .cpp
- 引入基于
std::unordered_map<RouteKey, HandlerFunc>的路由表机制,替代冗长的 if-else if 路由链 - 路由查找复杂度降至 O(1),大幅提升分发效率与代码可读性
- 引入基于
-
src/app/BusinessHandler.h & .cpp
- 重构为标准 Controller 层,所有 API 路由统一注册至 Router,实现解耦
-
src/base/FdCloser.h
- 新增文件描述符 RAII 封装类,确保
open()获取的 FD 在作用域结束时自动关闭,防止 FD 泄露
- 新增文件描述符 RAII 封装类,确保
-
src/app/SqlResultRAII.h(或集成于 SqlConnRAII)
- 强化 MySQL 资源管理,确保
MYSQL_RES*结果集在使用后自动释放
- 强化 MySQL 资源管理,确保
-
src/http/HttpContext.cpp
- 静态资源处理改用底层
open()+read()+FdCloser,彻底解决std::ifstream在异常路径下的 FD 泄露问题
- 静态资源处理改用底层
-
src/app/DbConnectionPool.cpp
GetConnection()中将sem_wait()替换为sem_timedwait()(超时 200ms),避免线程永久阻塞导致服务器假死- 超时后返回
nullptr,由上层业务逻辑处理连接获取失败,保障服务可用性
-
src/app/models/User.h & .cpp
- 所有数据库操作路径均通过
SqlConnRAII管理连接生命周期,杜绝连接泄漏
- 所有数据库操作路径均通过
-
路由编译错误
- 修正
#include "Router.h"为#include "app/Router.h",解决头文件找不到问题
- 修正
-
异步状态错乱
- 在
home.html前端引入加载状态锁与 Tab 版本校验,丢弃过期的异步响应,确保 UI 与数据一致
- 在
-
事务连接状态泄露
- 在涉及手动事务的代码路径中,采用结构化退出逻辑(如
do { ... } while(0)),确保无论成功或失败均恢复autocommit=1并回滚未提交事务
- 在涉及手动事务的代码路径中,采用结构化退出逻辑(如
-
文件描述符耗尽
- 全面审计静态文件处理逻辑,通过 RAII 保证所有打开的 FD 在任何执行路径下均被正确关闭
v4.2.0 标志着服务器架构的全面成熟:
- ✅ 高并发:Reactor 模型 + 线程池 + 超时保护
- ✅ 零资源泄露:连接、FD、SQL 结果集全 RAII 管理
- ✅ 清晰架构:路由表 + MVC 分层
- ✅ 稳定运行:可长期承载用户注册、登录及核心交互
核心变更: 实现了公共题库的展示与交互功能。用户现在可以浏览由系统或社区提供的公开题库,并支持将公共题库深度拷贝到个人空间进行学习和修改,同时统一了私有和公共题库的抽题数量为 10 题,优化了前端状态管理和 API 缓存控制。
-
src/app/models/Deck.h & .cpp 增强
- 新增
GetListPublic()方法,使用子查询(Sub-Query)优化 SQL 逻辑,精确统计卡片数量,确保在owner_user_id为NULL(系统题库)时也能正确显示 - 新增
CopyDeck(srcDeckId, targetUserId)方法,使用 SQL 事务和INSERT INTO ... SELECT语句,实现了题库信息和所有卡片数据的高效、原子化深度拷贝
- 新增
-
src/app/BusinessHandler.h & .cpp 增强
- 新增 API 接口:
POST /api/decks/copy:处理题库克隆请求,调用 Model 层进行事务拷贝GET /api/decks/public:获取公共题库列表
- 后端缓存控制:在所有 GET 和列表类 API 中,统一添加
Cache-Control: no-store等 Header,彻底禁用浏览器缓存,解决了前端数据加载错乱的问题
- 新增 API 接口:
-
resources/home.html 增强
- Tab 切换功能:实现“我的题库”与“公共题库”切换,并通过
localStorage记录当前 Tab 状态,防止刷新后状态丢失 - 公共题库交互:
- 选中公共题库时,底部操作栏动态切换,显示“📥 添加到我的题库”
- 隐藏“编辑信息”和“删除”按钮
- 学习逻辑统一:移除 URL 参数中的
limit逻辑
- Tab 切换功能:实现“我的题库”与“公共题库”切换,并通过
-
resources/study.html 增强
- 统一抽题限制:在
loadAndStart函数中,无论题库来源,强制使用data.slice(0, 10)截取前 10 张卡片进行学习,统一用户体验
- 统一抽题限制:在
- 数据同步错误:通过在
home.html的switchTab函数中清除选中状态,并使用后端强力禁止缓存的 Header,解决了切换 Tab 后数据延迟和 UI 状态错乱的问题 - SQL 健壮性:优化
Deck::GetListPublic的 SQL 语句,使其能够正确处理owner_user_id为NULL的公共题库,并准确返回卡片数量 - 前端错误处理:优化
loadDecks等函数,添加try/catch和“加载中”提示,提高了用户体验
核心变更: 在 v4.1.0 基础上,新增简易学习功能,支持从题库首页跳转至学习页面并开始随机抽题。
-
resources/study.html
- 新增学习页面,用于从指定题库中随机抽取卡片进行学习
-
resources/home.html
- 更新题库列表项,添加“开始学习”链接,可跳转至
study.html并携带题库 ID
- 更新题库列表项,添加“开始学习”链接,可跳转至
核心变更: 在 v4.0.0 基础上,进一步扩展了 Web 应用的功能,特别是增强了题库管理模块。新增了题库首页、增加和编辑题库信息以及卡片管理(包括添加、编辑、删除卡片)等功能,为用户提供了一个更完整的题库操作平台。
-
src/app/models/Card.h & .cpp
- 新增
Card数据模型(Model 层),用于表示题库中的每一张卡片 - 实现卡片的 CRUD 操作,确保每个卡片与一个特定的题库关联
- 新增
-
src/app/models/Deck.h & .cpp
- 新增
Deck数据模型(Model 层),代表题库的基本单元 - 提供创建、读取、更新、删除题库的方法,并支持在题库中添加或移除卡片
- 新增
-
resources/home.html
- 新增题库首页,展示所有可用题库列表,提供搜索和过滤功能,方便用户快速找到所需题库
-
resources/editor.html
- 新增题库编辑页面,允许用户添加新题库、编辑已有题库信息、以及管理题库下的卡片(包括添加、编辑和删除)
-
src/app/BusinessHandler.h & .cpp
- 扩展业务控制器以支持新的题库管理和卡片管理功能
- 新增
HandleDeck()和HandleCard()方法,分别处理题库和卡片相关的请求 - 支持通过 JSON API 进行题库和卡片的全栈操作,返回适当的 HTTP 状态码(200 成功 / 400 参数错误 / 404 资源未找到 / 409 冲突)
-
src/base/Config.h & .cpp
- 更新配置加载器,适应新添加的资源文件和路径,确保无缝集成到现有系统
-
src/http/HttpContext.h & .cpp
- 增强路由分发机制,以支持新的题库和卡片管理接口
- 更新
GenerateResponse()方法逻辑,使其能够正确处理针对题库和卡片的新请求类型
-
src/http/HttpRequest.h & .cpp
- 优化请求体解析逻辑,确保能有效处理涉及复杂数据结构(如题库包含多个卡片)的请求
-
src/http/HttpResponse.h & .cpp
- 调整响应生成逻辑,更好地支持动态内容响应,尤其是处理题库和卡片相关操作的结果
-
src/net/TcpConnection.cpp
- 微调主循环内的请求处理流程,确保新的题库和卡片管理请求可以被正确识别并高效处理
-
CMakeLists.txt
- 根据新增的资源文件和依赖关系,调整构建脚本,保证新功能模块能够顺利编译和部署
- 引入必要的前端资源文件(如
home.html和editor.html)到部署包中,确保它们能够在运行时正确访问
核心变更: 在 v3.2.0 基础上,完成从静态 WebServer 向动态 Web 应用的关键转型。全面集成 TiDB Cloud(MySQL 协议)数据库,实现基于 SSL/TLS 的安全连接池,并构建完整的 MVC 架构雏形。支持 JSON API 交互,打通用户注册与登录的全栈流程,为后续业务功能奠定坚实基础。
-
src/app/DbConnectionPool.h & .cpp
- 实现线程安全的 MySQL 连接池,通过复用连接显著降低高并发场景下的 TLS 握手开销
- 针对 TiDB Cloud 强制 TLS 要求,显式配置
MYSQL_OPT_SSL_CA指向isrgrootx1.pem证书文件 - 采用信号量(Semaphore)与互斥锁(Mutex)协同控制连接获取与归还,兼顾性能与安全性
-
src/app/SqlConnRAII.h
- 引入 RAII(Resource Acquisition Is Initialization)机制封装数据库连接生命周期
- 确保连接在作用域结束时自动归还至连接池,彻底杜绝连接泄漏风险
-
src/app/models/User.h & .cpp
- 新增
User数据模型(Model 层),封装用户表的 CRUD 操作 - 实现
Register()与Login()核心方法,直接与数据库交互,处理密码哈希(bcrypt)与唯一性校验
- 新增
-
src/app/BusinessHandler.h & .cpp
- 新增业务控制器(Controller 层),负责路由分发与逻辑协调
- 集成
nlohmann/json库,支持解析 JSON 请求体并构造结构化 JSON 响应 - 提供
HandleRegister()与HandleLogin()接口,规范返回 HTTP 状态码(200 成功 / 400 参数错误 / 401 认证失败 / 409 用户名冲突)
-
src/base/Config.h & .cpp
- 新增全局配置加载器,从
resources/config.json动态读取运行时参数 - 支持配置 Server 端口、线程数、数据库连接信息(含 SSL CA 路径),彻底移除硬编码
- 新增全局配置加载器,从
-
resources/config.json & index.html
- 新增 JSON 配置文件,统一管理环境敏感信息(如 TiDB 密码、CA 证书路径)
- 重构前端页面,集成 Fetch API 实现无刷新 AJAX 注册/登录交互,提升用户体验
-
src/http/HttpContext.h & .cpp
- 重构请求处理主流程,新增
GenerateResponse()方法实现路由分发(Routing) - 增强 POST 支持:修复原状态机无法完整读取 HTTP Request Body 的缺陷,确保 JSON 载荷正确解析
- 逻辑解耦:将静态资源处理剥离为
HandleStaticResource_(),动态 API 请求交由BusinessHandler处理
- 重构请求处理主流程,新增
-
src/http/HttpRequest.h & .cpp
- 新增
Body()访问器与SetBody()修改器,用于存储和传递 POST 请求的原始 JSON 数据 - 优化
IsKeepAlive()判定逻辑,严格兼容 HTTP/1.1 默认长连接语义
- 新增
-
src/http/HttpResponse.h & .cpp
- 支持动态内容响应:新增
SetBody()与body_成员,可直接返回 JSON 字符串而非仅 mmap 文件 - 重写报文生成逻辑,优先处理 API 响应,其次回退至静态文件;支持自定义 Header(如
Content-Type: application/json)
- 支持动态内容响应:新增
-
src/net/TcpConnection.cpp
- 在
HandleRead主循环中集成context_.GenerateResponse()调用,打通 网络层 → 协议层 → 业务层 的完整调用链
- 在
-
CMakeLists.txt
- 新增
pkg-config查找mysqlclient依赖,确保正确链接 MySQL 客户端库 - 集成
nlohmann_json(header-only)与libmysqlclient,完善构建依赖 - 优化构建脚本,建议通过软链接或复制命令将
resources/目录纳入部署包
- 新增
核心变更: 引入高性能、仅头文件的 C++ 日志库 spdlog,替换原有 简易日志实现,提供多线程安全、格式化输出、日志级别控制及文件滚动等企业级日志功能。
- 第三方依赖
- 集成
spdlogv1.14.1(通过third_party/spdlog/子模块或直接包含)。
- 集成
- 日志配置支持
- 支持通过
config.json动态设置日志级别(如"log_level": "DEBUG")。 - 支持同时输出到 控制台(带颜色) 和 日志文件。
- 启用 每日/按大小滚动 文件日志(默认保留最近 7 天)。
- 支持通过
- 全局日志接口
- 提供统一宏:
LOG_INFO,LOG_WARN,LOG_ERROR,LOG_DEBUG等,便于全项目使用。
- 提供统一宏:
-
异步日志丢失问题
在异步日志模式下,日志消息先写入内存队列,由后台线程异步刷新到文件。若程序运行时间过短、提前进入阻塞循环或异常退出,可能导致缓冲区中的日志未及时落盘,表现为:- 终端可正常输出日志(因控制台 sink 同步),
- 但日志文件内容缺失或不完整。
-
解决方案
在InitLogger()中启用 定时自动刷新策略,确保即使程序未显式调用spdlog::shutdown(),日志也能定期写入磁盘:// Log.cpp - InitLogger() // spdlog::set_default_logger(async_logger); // spdlog::flush_every(std::chrono::seconds(3)); // 每 3 秒强制刷新一次
核心变更: 在 v3.0.0 多线程 Reactor 架构基础上,新增高精度、低开销的定时器功能,支持连接超时断开等典型网络服务场景。通过最小堆(Min-Heap)实现高效定时任务调度,并深度集成至 EventLoop
- src/net/Timer.h & Timer.cpp
- 定义
Timer类,封装定时任务的回调函数、超时时间、是否重复执行等属性 - 使用
std::chrono提供类型安全的时间操作
- 定义
- src/net/TimerId.h
- 引入
TimerId轻量句柄,用于安全地取消已注册的定时器
- 引入
- src/net/TimerQueue.h & TimerQueue.cpp
- 实现基于 最小堆(std::priority_queue) + 时间轮辅助优化 的
TimerQueue - 提供
addTimer()和cancel()接口,支持跨线程安全注册/取消定时任务 - 内部通过
EventLoop::runInLoop()保证线程安全,避免锁竞争
- 实现基于 最小堆(std::priority_queue) + 时间轮辅助优化 的
- src/net/EventLoop.h & .cpp 增强
- 新增
runAt(),runAfter(),runEvery()系列接口,简化定时器使用 - 集成
TimerQueue,在每次epoll_wait返回后自动检查并触发到期定时器
- 新增
- 连接超时自动关闭示例
- 在
TcpConnection初始化时可选注册超时回调,若客户端在指定时间内无活动则主动断开连接
- 在
核心变更: 架构发生质变,从单线程 Reactor 升级为 Main-Sub Reactor 多线程架构。主线程只负责分发连接,子线程池负责高并发读写,充分利用多核 CPU。
- src/net/EventLoopThreadPool.cpp & .h
- 实现了线程池管理类,负责创建和管理多个 EventLoop 线程。
- 实现了 Round-Robin (轮询) 调度算法,将新连接均匀分配给子线程。
- src/net/EventLoop.cpp 增强
- 新增 跨线程唤醒机制:引入 eventfd (wakeupFd_),允许主线程唤醒阻塞在 epoll_wait 中的子线程。
- 新增 任务队列 (pendingFunctors_):实现了 RunInLoop 和 QueueInLoop,允许在指定线程中安全执行回调任务。
- src/server/TcpServer.cpp
- 集成 EventLoopThreadPool,默认开启 4 个工作线程(可配置)。
- OnNewConnection 逻辑变更:不再使用主线程 Loop,而是从线程池获取 ioLoop 创建 TcpConnection。
- 增加了 std::mutex 互斥锁,保证多线程环境下 connections_ Map 的线程安全。
- src/net/TcpConnection.cpp
- 发送逻辑重构:优化了 send 处理逻辑,正确处理非阻塞 I/O 下的 EAGAIN 错误,防止高并发下的死锁或数据丢失。
- 移除了 usleep 等阻塞操作,实现了极致的非阻塞性能。
- src/http/HttpRequest.cpp
- Keep-Alive 修复:修正了 HTTP/1.1 默认长连接的判断逻辑,并增加了对 Header 大小写不敏感的支持,解决了 ab 压测连接重置的问题。
在 WSL2 环境下,使用 wrk 进行 4 线程 500 并发持续 30 秒的压力测试,结果如下:
- QPS (Requests/sec): 110,220.52 (11万+)
- 吞吐量 (Transfer/sec): 583.07MB
- 延迟 (Latency): 平均 3.59ms,99% 请求在 28ms 内完成。
- 稳定性: 338万次请求 0 失败,0 超时。
测试数据(裸机性能,几乎没有业务)
// 4线程 500并发
Running 30s test @ http://127.0.0.1:8080/
4 threads and 500 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 3.59ms 28.83ms 607.91ms 99.36%
Req/Sec 28.20k 9.46k 48.71k 70.02%
3383176 requests in 30.69s, 17.48GB read
Requests/sec: 110220.52
Transfer/sec: 583.07MB
| 指标 | T=4 | T=6 | T=8 | T=6 → T=8 变化 | 评价 |
|---|---|---|---|---|---|
| QPS (Requests/sec) | 110,220.52 | 113,982.80 | 111,959.73 | QPS 开始下降,达到性能拐点。 | |
| 平均延迟 (Avg Latency) | 3.59 ms | 2.96 ms | 3.14 ms | 平均响应时间变长,效率降低。 | |
| 最大延迟 (Max Latency) | 607.91 ms | 519.28 ms | 570.65 ms | 尾部延迟恶化,系统稳定性下降。 | |
| 延迟标准差 (Stdev) | 28.83 ms | 22.72 ms | 25.47 ms | 延迟波动性增大,竞争加剧。 | |
| 总请求数 | 3,383,176 | 3,481,717 | 3,429,809 | - | 总处理量略有下降。 |
| 指标 | T=6, C=300 (轻载) | T=6, C=500 (最佳点) | T=6, C=700 (高压饱和) | 相对 C=500 变化 |
|---|---|---|---|---|
| QPS (Requests/sec) | 115,159.60 | 113,982.80 | 112,876.17 | |
| 平均延迟 (Avg Latency) | 3.13 ms | 2.96 ms | 4.51 ms | |
| 最大延迟 (Max Latency) | 605.95 ms | 519.28 ms | 671.70 ms | |
| 延迟标准差 (Stdev) | 29.61 ms | 22.72 ms | 32.95 ms | |
| 总请求数 | 3,527,387 | 3,481,717 | 3,470,530 | - |
| 最佳配置 | 关键指标 | 评价 |
|---|---|---|
| 线程数 (T) | 6 | 提供了最高的并行处理能力。 |
| 并发量 (C) | 500 | 实现了最低的平均延迟 ( |
| 容量上限 |
|
系统的物理瓶颈。 |
最佳线程数量接近6,并发数500;
核心变更: 进一步拆分 TcpServer 的职责,实现完全解耦的 Reactor 模型。
- src/net/Acceptor.cpp & .h
- 专门负责监听套接字 (listenFd) 的生命周期管理。
- 封装了 bind, listen 以及 accept 逻辑。
- 当有新连接到达时,通过回调函数通知 TcpServer。
- src/net/TcpConnection.cpp & .h
- 封装一个已连接的客户端 (clientFd)。
- 持有该连接的 Socket, Channel, Buffer 和 HttpContext。
- 负责处理该连接的 OnMessage (读取->解析->发送) 和 OnClose。
- src/server/TcpServer.cpp
- 移除了 listener_ 和 listenChannel_,改由 Acceptor 接管。
- 移除了 buffers_ 和 users_ (Map),改由 TcpConnection 对象自我管理(或由 TcpServer 持有 Connection Map)。
- 代码变得非常精简,只负责将 Acceptor 产生的新连接包装成 TcpConnection。
核心变更: 实现了基于 mmap 的静态文件读取与发送,支持 HTML/图片/CSS 等多种文件类型。
- resources/
- 新增静态资源目录及演示文件 (index.html)。
- src/http/HttpResponse.cpp
- 实现了 MakeResponse 核心逻辑:
- 根据请求路径拼接服务器绝对路径。
- 使用 stat 系统调用检查文件存在性及权限 (404/403 处理)。
- 使用 mmap (内存映射) 零拷贝技术读取文件内容。
- 根据文件后缀自动推断 Content-Type。
- 实现了 UnmapFile 自动释放内存资源。
- 实现了 MakeResponse 核心逻辑:
- src/http/HttpContext.cpp
- 在 Init 中实现了自动探测当前运行目录 (getcwd) 并拼接资源路径的逻辑。
- 修复了 response_ 对象初始化时路径为空,导致无法正确找到 index.html 的 Bug。
- 修复了 CMake 构建时未将 resources 目录复制到 build 目录导致的 404 问题。
核心变更: 从“裸 Epoll 循环”升级为标准的 Reactor 模型,实现了 Acceptor 与 IO 处理的解耦。
- src/net/Channel.cpp & .h
- 封装了文件描述符 (fd) 及其关注的事件 (events)。
- 实现了回调机制 (std::bind),分发 Read, Write, Close, Error 事件。
- 充当 EventLoop 与 Socket 之间的桥梁。
- src/net/EventLoop.cpp & .h
- 实现了核心事件循环 (Loop),取代了 TcpServer 中的 while(true)。
- 负责驱动 Epoll 并调度活跃的 Channel 执行回调。
- src/net/Epoll.cpp
- 重大重构:epoll_event.data.ptr 从存储 fd (int) 改为存储 Channel* 指针。
- 新增 UpdateChannel 接口,支持 EPOLL_CTL_MOD 和 EPOLL_CTL_ADD 的自动切换。
- src/server/TcpServer.cpp
- 移除了底层的 epoll_wait 循环,控制权移交 EventLoop。
- 重构了连接处理逻辑:
- OnNewConnection: 处理新用户连接。
- OnMessage: 处理已连接用户的读写事件。
- 修复了 EventLoop 到 Epoll 调用链断裂导致服务器无法监听的问题。
核心变更: 实现了应用层协议解析,服务器能够处理浏览器请求并返回 HTML 页面。
- src/http/HttpRequest.cpp & .h
- 定义 HTTP 请求实体,存储解析后的 Method, URL, Version, Headers。
- src/http/HttpResponse.cpp & .h
- 实现了标准 HTTP 响应报文的构造(状态行、Header、Body)。
- 暂时使用硬编码的 "Hello, WebServer!" HTML 用于测试。
- src/http/HttpContext.cpp & .h
- 实现了 有限状态机 (Finite State Machine) 解析 HTTP 协议。
- 支持解析请求行 (REQUEST_LINE)、请求头 (HEADERS) 和请求体 (BODY)。
- src/server/TcpServer.cpp
- OnMessage 逻辑升级:从单纯的 TCP 回显 (Echo) 改为 HTTP 请求/响应处理。
- 集成 HttpContext,当解析成功时返回 200 OK,失败时记录日志或关闭连接。
- 修复了浏览器访问时一直“转圈 (Pending)”的问题(原因:解析失败或数据处理分支缺失导致死锁)。
- 解决了 HTTP 响应头缺失 Content-Length 导致 Keep-Alive 连接无法正确结束的问题。
核心变更: 引入自动扩容缓冲区,解决 TCP 粘包/拆包问题,优化内存读写。
- src/base/Buffer.cpp & .h
- 实现了类似 std::vector 的动态缓冲区。
- 核心优化:利用 readv (分散读) 系统调用,结合栈上临时空间 (extrabuf),减少系统调用次数并实现自动扩容。
- 提供了 Retrieve, Peek, Append 等标准接口供上层使用。
- 编译错误修复:移除了 Buffer 类成员变量中的 std::atomic,解决了 Buffer 对象无法被拷贝/移动导致无法存入 std::map 的问题。
- CMake 配置:更新 CMakeLists.txt,加入 src/base 目录编译支持。
核心变更: 项目初始化,搭建基于 WSL 的开发环境,实现基于 Epoll 的 TCP 回显服务器。
- 基础网络组件
- Socket: 封装 socket, bind, listen, accept, setsockopt 等系统调用 (RAII 风格)。
- Epoll: 封装 epoll_create, epoll_ctl, epoll_wait。
- TcpServer: 管理监听套接字和客户端连接。
- 构建系统
- CMakeLists.txt: 配置项目结构,支持自动扫描源文件。
- 开发环境
- 配置 Windows Subsystem for Linux (WSL2 / Ubuntu)。
- 解决 Windows 与 Linux 文件系统权限不兼容导致的 CMake 编译错误 (Operation not permitted),将项目迁移至 Linux Home 目录。
- 实现了基础的 Echo Server:客户端发送什么,服务器原样返回。
- 采用 Epoll Edge Trigger (ET) 边缘触发模式 + 非阻塞 I/O。
- 验证了 nc (netcat) 命令行的连接与收发测试。