从零手写高性能 C++ TCP 服务器框架(一):项目介绍
本系列将从零开始,手写一个工业级的高性能 C++ TCP 服务器框架,涵盖 Reactor 模型、epoll 多路复用、时间轮定时器、多线程线程池等核心知识点,最终构建出支持 HTTP 协议的完整服务端框架。
一、项目是什么
本项目实现了一个基于 Reactor 模式 + epoll + 多线程 的高性能 TCP 服务器框架,代码量约 1100 行,麻雀虽小五脏俱全。
基于这个框架,项目实现了两个完整的应用:
| 应用 | 功能 |
|---|---|
| Echo Server | 回显服务器,客户端发什么就回什么,是框架用法的最简演示 |
| HTTP Server | 支持静态文件服务、MIME 类型识别、HTTP 状态码管理的完整 HTTP 服务端 |
二、项目技术栈
需要具备的前置知识
这不是一个入门级项目,需要一定的 C++ 基础和 Linux 系统编程基础。
1. C++ 基础(核心)
| 知识点 | 在项目中的用途 |
|---|---|
STL 容器:vector、unordered_map |
Buffer 缓冲区、连接管理哈希表 |
智能指针:shared_ptr、weak_ptr |
连接生命周期管理,防止野指针 |
函数对象:std::function、std::bind |
事件回调机制 |
多线程:std::thread、mutex、condition_variable |
工作线程池、线程间同步 |
类型擦除:Any 模式 |
连接上下文存储 |
| 移动语义与 RAII | 资源安全管理 |
2. Linux 系统编程(核心)
| 系统调用 / 机制 | 在项目中的用途 |
|---|---|
socket / bind / listen / accept |
服务端套接字创建与连接接入 |
epoll_create / epoll_ctl / epoll_wait |
I/O 多路复用,监控海量连接 |
eventfd |
线程间唤醒,打断阻塞的 epoll_wait |
timerfd_create |
精确定时,驱动时间轮 |
非阻塞 I/O(O_NONBLOCK) |
避免 I/O 操作阻塞事件循环 |
信号屏蔽(SIGPIPE) |
防止对端关闭时进程崩溃 |
3. 网络编程基础
-
TCP 三次握手与四次挥手的过程
-
TCP 半关闭状态(
shutdownvsclose) -
粘包/拆包问题的处理思路
-
HTTP/1.1 请求/响应报文格式
三、项目核心模块
项目由 11 个核心类组成,各自职责清晰:
Buffer → 应用层读写缓冲区(解决粘包,避免频繁系统调用)
Socket → 套接字封装(RAII,统一管理 fd 生命周期)
Channel → 事件通道(描述符 + 事件 + 回调,解耦 IO 与业务)
Poller → epoll 封装(管理所有 Channel 的事件监控)
TimerWheel → 时间轮定时器(O(1) 的定时任务管理)
EventLoop → 事件循环(I/O + 定时器 + 任务队列,单线程无锁)
LoopThread → EventLoop 线程(将 EventLoop 运行在独立线程中)
LoopThreadPool→ 线程池(主从 Reactor 的从属部分)
Any → 类型擦除容器(存储连接的业务上下文)
Connection → 连接管理(核心类,管理读写/状态/定时/回调)
Acceptor → 监听管理(专门处理新连接的接入)
TcpServer → 服务器主类(整合所有组件,对外提供接口)
四、学完这个项目你能收获什么
技术硬实力
1. 真正理解 Reactor 模型
不再是停留在"听说过"的阶段,而是亲手实现主从 Reactor 模型,清楚地知道主线程只负责 accept 新连接、工作线程负责处理已连接 socket 的全部 I/O 事件,以及为什么这样设计能大幅提升并发能力。
2. 掌握 epoll 的正确使用姿势
理解 ET 模式(边缘触发)与 LT 模式(水平触发)的区别,掌握在非阻塞模式下如何用循环读完所有数据,避免数据残留或 CPU 空转。
3. 学会用时间轮管理定时任务
告别粗糙的 sleep 和低效的最小堆,用 timerfd + 时间轮实现 O(1) 复杂度的定时任务添加、刷新、取消,理解为什么 Nginx、Kafka 都在用这个思路。
4. 理解 EventLoop + 任务队列的线程安全模型
框架所有对连接的操作都通过 RunInLoop / QueueInLoop 派发到连接所属线程中执行,彻底避免多线程竞争,不需要对业务数据加锁。这是 Muduo、Netty、Nginx 等知名框架的共同设计哲学。
5. 亲手实现 HTTP 解析
从字节流中手动解析 HTTP 请求行、请求头、请求体,处理 MIME 类型、状态码、静态文件响应,深刻理解 HTTP 协议的报文格式。
6. 理解 C++ 资源管理的工程实践
通过 shared_ptr + RAII + 状态机管理连接的完整生命周期,理解为什么连接的 Release 要通过 QueueInLoop 而不是 RunInLoop 执行,这类细节正是高级 C++ 工程师与初学者的差距所在。
求职竞争力
这个项目不仅仅是一个练手项目,而是一个有完整工程深度的项目,面试时可以聊的点极多:
-
为什么用 epoll 而不是 select/poll?(接口、性能、内核实现原理)
-
主从 Reactor 的设计思路? (单 Reactor 的瓶颈,多线程如何分工)
-
非活跃连接是怎么释放的? (时间轮 + timerfd + shared_ptr 引用计数)
-
如何保证线程安全,有没有加锁? (RunInLoop 模型,零锁设计)
-
Buffer 为什么这样设计? (读写偏移、数据移动 vs 扩容策略)
这些问题,写过这个项目的人可以条理清晰地回答,没写过的人只能泛泛而谈。
五、项目模块拆解与系列规划
本系列将按模块逐一拆解,每篇文章聚焦一个核心组件,代码 + 原理 + 设计思路三位一体:
| 篇号 | 内容 |
|---|---|
| (一) | 项目介绍:项目定位、技术栈、核心模块总览、模块拆解与系列规划 |
| (二) | 名词介绍:HTTP 服务器、Reactor 模式(单/多)、主从 Reactor 模型 |
| (三) | 模块介绍和模块关系图:Server 模块 / 协议模块划分,各子模块职责 |
| (四) | 前置知识介绍:C++ bind、function、shared_ptr、unique_ptr、Any 类型擦除 |
| (五) | Buffer 缓冲区实现:vector<char> 读写缓冲区,粘包处理 |
| (六) | 封装日志宏和 Socket 套接字:日志宏定义,RAII 套接字封装 |
| (七) | Channel 模块和 Poller 模块实现:描述符事件管理,回调机制设计,epoll 多路复用封装 |
| (八) | 时间轮定时器实现:TimerWheel 实现,O(1) 定时任务管理 |
| (九) | EventLoop 实现:事件循环,doPendingFunctors 批量执行,跨线程任务执行 |
| (十) | EventLoop 和 TimerWheel 联调:定时器与事件循环结合,实现连接超时管理 |
| ( 十一 ) | Connection 实现:连接封装,读写回调,超时关闭,状态机管理 |
| (十二) | Acceptor、LoopThread 以及 LoopThreadPool 实现:主从 Reactor 架构,主 Reactor 接收连接,LoopThread 独立线程,线程池轮询分发 |
| (十三) | TcpServer 实现:整合所有模块,构建完整 TCP 服务器,组装 Acceptor + Connection 管理 |
| (十四) | HTTP 模块介绍:HTTP 协议概述,请求/响应报文格式,协议解析思路 |
| (十五) | Util 工具实现:URL 编解码、MIME 映射、文件读写、路径安全校验 |
| (十六) | HttpResponse 和 HttpRequest 实现:HTTP 响应/请求数据结构,状态码、头部、body 封装 |
| (十七) | HttpContext 和 HttpServer 实现:HTTP 解析状态机构建,HttpServer 整合 TcpServer 实现完整 HTTP 服务器 |
| (十八) | Http 的相关测试:curl 命令测试 HTTP 服务器各接口,功能验证与调试 |
六、适合谁看
✅ 有 C++ 基础,想进阶网络编程的同学 ✅ 学过 Linux 系统编程,想把知识串联成项目的同学 ✅ 准备 C++ 后台 / 服务端 / 基础架构岗面试的同学 ✅ 想深入理解 Muduo 设计思想的同学
❌ 完全没有 C++ 基础的同学(建议先补 STL 和现代 C++) ❌ 想找到一键运行的业务项目(这是框架,不是业务)
写在最后
网络编程是 C++ 后台开发的核心门槛,而真正理解它的最好方式,不是看书,不是背八股,而是亲手实现一遍。
这个框架的代码不复杂,但每一行都有它的道理。后续每一篇文章,我们都会把"为什么这么写"讲透,而不仅仅是贴代码。
如果觉得有帮助,点个赞 + 收藏,我们下一篇见。