嘿,小伙伴们好!我是小康👋
下半年小康自研实现了 11 个 C++ 硬核项目:
线程池、内存池、MySQL连接池、多线程下载工具、
内存泄漏检测工具、ReactorX、日志库minispdlog,无锁栈、
无锁队列SPSC,无锁队列MPMC,工业级shared_ptr。
今天,我要带来一个更加重磅的项目——基于Reactor的高性能网络库实战!这不是简单的组件升级,而是一次完整的架构蜕变,让你真正掌握从底层组件到上层应用的完整技术栈。
为什么要学习网络库开发?
先说个扎心的现实:
市面上的开源网络库(muduo、libevent、Boost.Asio等)动辄上万行代码,文档晦涩,想要从零开始实现?几乎不可能!即使你想参考这些项目学习,也很难理清楚整个架构的设计思路。
更要命的是:
- 看懂 ≠ 会写:能读懂muduo源码的人很多,但能从0到1实现的人很少
- 改代码 ≠ 掌握:在GitHub上改改现有项目,学到的只是皮毛
- 面试难:面试官问"你是怎么设计这个网络库的",你说"我抄袭了muduo"——这就尴尬了
而我的课程主打的就是:手把手带你从0到1实现,让你真正理解每一行代码为什么这么写,这个思路才是最重要的!
这个网络库项目有什么不同?
核心优势:渐进式教学,层层递进
我把整个网络库分成了两个阶段:
- 前5天:Reactor核心组件(EventLoop、Poller、Timer等)
- 后5天:网络库上层应用(Socket、Buffer、TcpConnection、TcpServer等)
这种设计有两个好处:
- 如果你已经学过我的Reactor项目,可以直接从第6天开始学习
- 如果你是新学员,10天完整学习,从底层到上层一气呵成
架构一览:Multi-Reactor模型
┌─────────────────────────────────────┐
│ 用户应用层 │
│ EchoServer / HttpServer / RPC │
└─────────────────┬───────────────────┘
│
┌─────────────────┴───────────────────┐
│ TcpServer │
│ ┌──────────────────────────────┐ │
│ │ Acceptor (监听新连接) │ │
│ │ ThreadPool (IO线程池) │ │
│ │ TcpConnection (连接管理) │ │
│ └──────────────────────────────┘ │
└─────────────────┬───────────────────┘
│
┌──────────────────────┼──────────────────────┐
│ │ │
┌───────┴────────┐ ┌───────┴────────┐ ┌───────┴────────┐
│ Main Reactor │ │ Sub Reactor 1 │ │ Sub Reactor N │
│ (主线程) │ │ (IO线程1) │ │ (IO线程N) │
│ ↓ │ │ ↓ │ │ ↓ │
│ Acceptor │ │ TcpConn1 │ │ TcpConnN │
│ (listenfd) │ │ TcpConn2 │ │ TcpConnN+1 │
└────────────────┘ └────────────────┘ └────────────────┘
│ │ │
└──────────────────────┴──────────────────────┘
EventLoop + Poller
这个架构的精妙之处在于:
- 主Reactor只负责accept新连接(极快)
- 从Reactor池负责所有IO操作(充分利用多核)
- Round-Robin负载均衡(连接均匀分配)
10天完整教学大纲
第一阶段:Reactor核心组件(Day 1-5)
Day 1:打地基 - epoll封装与Channel抽象
├─ 理解 Reactor 模式的核心思想
├─ Poller实现(epoll的优雅封装)
├─ Channel实现(事件分发的艺术)
├─ 事件回调机制设计
└─ 实战:监听标准输入事件
Day 2:核心引擎 - EventLoop事件循环
├─ EventLoop + One Loop Per Thread单线程版本
├─ 事件循环的启动/停止机制
├─ Channel注册/更新/移除
└─ 实战:echo server(单连接版)
Day 3:时间之轮 - TimerQueue定时器
├─ 将定时器纳入统一事件处理
├─ Timer和TimerId实现
├─ TimerQueue(基于timerfd的高性能设计)
├─ 定时器添加/取消机制
└─ 实战:定时打印 + 自动断连
Day 4:跨线程通信 - EventLoopThread与线程池
├─ EventLoopThread实现
├─ EventLoopThreadPool(线程池封装)
├─ eventfd跨线程任务投递
└─ 实战:多线程echo server
Day 5:性能优化与完整测试
├─ 打造生产级组件
├─ 性能测试工具benchmark编写
├─ QPS/延迟压测对比
├─ 使用示例与最佳实践
└─ Reactor阶段总结
第二阶段:网络库上层应用(Day 6-10)
Day 6:网络基础设施 - Socket封装
├─ Socket RAII封装(资源自动管理)
├─ InetAddress地址类(IPv4支持)
├─ SocketsOps工具函数集
│ ├─ createNonblockingOrDie
│ ├─ bindOrDie / listenOrDie
│ ├─ accept(支持accept4)
│ └─ 地址转换函数
└─ 实战:基本socket创建、绑定、监听测试
Day 7:连接接受器 - Acceptor组件
├─ Acceptor类实现(listening socket封装)
├─ 集成到EventLoop
├─ 新连接回调机制
├─ idleFd技巧(优雅处理fd耗尽)
└─ 实战:accept新连接并发送欢迎消息
Day 8:缓冲区设计 - Buffer自动扩容
├─ 高效应用层Buffer实现
│ ├─ 三区域设计(prepend/readable/writable)
│ ├─ 自动扩容机制
│ └─ 内部空间调整优化
├─ readFd优化(scatter-gather IO)
│ ├─ readv系统调用
│ ├─ 栈上临时缓冲(64KB)
│ └─ 一次读取所有数据
├─ 常用操作接口
│ ├─ peek / retrieve / append
│ ├─ findCRLF(HTTP解析)
│ └─ 整数序列化(网络字节序)
└─ 实战:Buffer各种操作测试
Day 9:TCP连接 - TcpConnection核心
├─ TcpConnection类完整实现
│ ├─ 状态机设计(4种状态)
│ ├─ 生命周期管理
│ │ ├─ shared_ptr + enable_shared_from_this + weak_ptr
│ │ └─ tie机制(防止提前析构)
│ ├─ 读写事件处理
│ │ ├─ handleRead(Buffer接收)
│ │ ├─ handleWrite(异步发送)
│ │ └─ handleClose(优雅关闭)
│ └─ 用户回调接口
│ ├─ ConnectionCallback
│ ├─ MessageCallback
│ ├─ WriteCompleteCallback
│ └─ HighWaterMarkCallback
├─ Channel的tie机制升级
|──实现完整的读写逻辑
|──实现优雅关闭机制
└─ 实战:完整echo服务器(单线程版)
Day 10:TCP服务器 - TcpServer与Multi-Reactor
├─ TcpServer类实现(核心粘合层)
│ ├─ Acceptor集成
│ ├─ EventLoopThreadPool集成
│ ├─ TcpConnection管理(map)
│ └─ Round-Robin负载均衡
├─ 连接建立流程
│ ├─ Main Reactor accept
│ ├─ 选择Sub Reactor
│ ├─ 创建TcpConnection
│ └─ 注册到IO线程
├─ 连接断开流程
│ ├─ handleClose处理
│ ├─ 跨线程移除
│ └─ 优雅析构
├─ 单线程/多线程模式切换
└─ 实战:
├─ 单线程echo服务器
├─ 多线程echo服务器(4线程)
└─ 性能压测(QPS/并发测试)
核心代码展示
让我们看看TcpConnection的核心发送逻辑(这是网络库最精华的部分):
void TcpConnection::sendInLoop(const void* data, size_t len)
{
loop_->assertInLoopThread();
ssize_t nwrote = 0;
size_t remaining = len;
bool faultError = false;
// 状态检查
if (state_ == kDisconnected) {
std::cerr << "disconnected, give up writing" << std::endl;
return;
}
// 优化:如果没有待发送数据且Channel未关注写事件,直接write
if (!channel_->isWriting() && outputBuffer_.readableBytes() == 0) {
nwrote = sockets::write(channel_->fd(), data, len);
if (nwrote >= 0) {
remaining = len - nwrote;
// 一次性写完,触发WriteCompleteCallback
if (remaining == 0 && writeCompleteCallback_) {
loop_->queueInLoop(std::bind(writeCompleteCallback_,
shared_from_this()));
}
} else {
nwrote = 0;
if (errno != EWOULDBLOCK) {
std::cerr << "TcpConnection::sendInLoop error" << std::endl;
if (errno == EPIPE || errno == ECONNRESET) {
faultError = true;
}
}
}
}
// 未写完的数据放入outputBuffer_,并关注EPOLLOUT事件
assert(remaining <= len);
if (!faultError && remaining > 0) {
size_t oldLen = outputBuffer_.readableBytes();
// 高水位回调检查
if (oldLen + remaining >= highWaterMark_
&& oldLen < highWaterMark_
&& highWaterMarkCallback_) {
loop_->queueInLoop(std::bind(highWaterMarkCallback_,
shared_from_this(), oldLen + remaining));
}
outputBuffer_.append(static_cast<const char*>(data) + nwrote, remaining);
if (!channel_->isWriting()) {
channel_->enableWriting(); // 关注写事件
}
}
}
这段代码展示了:
- 零拷贝优化:直接write,避免不必要的buffer拷贝
- 异步发送:未写完的数据放入buffer,通过EPOLLOUT继续发送
- 高水位控制:防止发送缓冲区无限增长
- 线程安全:所有操作都在IO线程进行
实际使用:3分钟搭建Echo服务器
#include "reactor/TcpServer.h"
#include "reactor/EventLoop.h"
#include "reactor/InetAddress.h"
using namespace reactor;
class EchoServer {
public:
EchoServer(EventLoop* loop, const InetAddress& addr, int threadNum)
: server_(loop, addr, "EchoServer")
{
server_.setConnectionCallback(
std::bind(&EchoServer::onConnection, this, _1));
server_.setMessageCallback(
std::bind(&EchoServer::onMessage, this, _1, _2, _3));
server_.setThreadNum(threadNum); // 设置IO线程数
}
void start() { server_.start(); }
private:
void onConnection(const TcpConnectionPtr& conn) {
std::cout << conn->peerAddress().toIpPort()
<< (conn->connected() ? " UP" : " DOWN") << std::endl;
}
void onMessage(const TcpConnectionPtr& conn,
Buffer* buf, Timestamp time) {
std::string msg(buf->retrieveAllAsString());
conn->send(msg); // echo back
}
TcpServer server_;
};
int main() {
EventLoop loop;
InetAddress addr(9999);
EchoServer server(&loop, addr, 4); // 4个IO线程
server.start();
loop.loop(); // 开始事件循环
return 0;
}
看到了吗?
- 不到50行代码
- 高性能Multi-Reactor架构
- 支持数万并发连接
- 可直接用于生产环境
学完这个项目,你将获得什么?
💎 技术能力提升
- 完整的网络编程知识体系
- TCP/IP协议栈深度理解
- epoll、eventfd、timerfd系统调用
- 非阻塞IO与Reactor模式
- Multi-Reactor多线程架构
- 现代C++工程实践
- C++11/14智能指针、lambda、右值引用
- RAII资源管理模式
- 模板编程与泛型设计
- 回调机制与异步编程
- 系统架构设计能力
- 组件化设计思想
- 接口抽象与职责分离
- 生命周期管理技巧
- 性能优化方法论
💎 实战项目经验
- 可以直接用于生产的网络库
- 不是玩具Demo,而是真正可用的基础设施
- 支持HTTP、RPC等上层协议开发
- 1500+行核心代码,经过严格测试
- 面试加分项
- “我从0到1实现了一个高性能网络库”
- 能清晰讲解Multi-Reactor架构设计
- 能回答muduo、libevent等开源库的原理问题
- 后续扩展基础
- 基于此网络库开发HTTP服务器
- 实现RPC框架(类似gRPC)
- 开发WebSocket服务器
- 构建分布式系统组件
- …
后续系列课程预告
基于这个网络库,我计划推出以下系列课程:
HTTP服务器实战(预计5天)
├─ HTTP协议解析(GET/POST/Header)
├─ HttpRequest和HttpResponse封装
├─ 路由系统设计
├─ 静态/动态文件服务
└─ .....
RPC框架实战(预计7天)
├─ Protobuf协议集成
├─ 服务注册与发现
├─ 负载均衡策略
├─ 异步调用与超时控制
└─ 完整RPC框架(类似gRPC)
WebSocket服务器(预计5天)
├─ WebSocket协议实现
├─ 握手与帧解析
├─ 心跳检测
└─ 聊天室应用
└─ ....
重要说明:这些系列课程是否开设,取决于大家的需求。如果这次网络库项目报名人数多、反馈好,我会优先开发这些系列课程,让大家的学习路径更完整!
项目课程特色
1. 渐进式教学,降低学习门槛
不是一上来就扔给你1万行代码,而是:
- 每天一个小目标,循序渐进
- 每个版本都能独立运行
- 清晰看到项目从简单到复杂的演化过程
2. 原创设计
这是我完全从0到1设计和实现的网络库,也参考了muduo的一些优秀设计:
- 每一行代码都经过深思熟虑
- 每个设计决策都能讲清楚为什么
3. 完整的学习资料包
- 2200+行核心代码(含详细注释),加上测试 3500+ 行
- 10天分步教学文档(每天都有明确目标)
- 完整测试代码(1300+行,覆盖所有场景)
- CMake构建系统(跨平台编译)
- 架构设计文档(理解设计思路)
- 性能测试报告(QPS、延迟、吞吐量等)
📞 如何找我?
微信搜索 jkfwdkf 添加
备注:「 网络库」
最后想说的话
从"能看懂muduo源码"到"能自己实现网络库",这不仅仅是技术能力的跨越,更是思维方式的升级。
我做这个项目的初衷很简单:
- 让更多人能真正理解高性能网络编程
- 不只是API调用者,更是架构设计者
- 拥有可以自信讲解的深度项目经验
10天时间,每天1小时,你就能拥有:
- ✅ 一个完整的高性能网络库
- ✅ 从底层到上层的完整知识体系
- ✅ 可以继续扩展的技术基础
- ✅ 面试中的强力武器
微信:jkfwdkf
备注:网络库
期待与真正想提升实战能力的你一起进步!💪
其他 C++ 硬核项目:
网上的 shared_ptr 都是玩具?我用半个月造了个工业级的 !
手把手带你实现MPMC无锁队列:6天从Facebook Folly到自研Thunder Queue
C++无锁编程进阶实战:手把手打造极速 SPSC 队列!
C++无锁编程终极实战:手把手带你实现工业级无锁栈!
ReactorX项目火了!腾讯/字节面试官都在问的Reactor模式,终于有人讲透了
被内存泄漏折磨疯了的我,写了个工具,现在同事都来借用…
手撸线程池才是C++程序员的硬实力!7天手把手带你从0到1完整实现
从 0 到 1 实现高性能日志库 MiniSpdlog — 这可能是最适合新手的日志系统实战项目 !
三周肝出4000行代码,我的内存池竟然让malloc"破防"了!性能暴涨7.37倍背后的技术真相
手撸4200行MySQL连接池,8天带你搞定后端核心组件!
终于有人把C++多线程下载工具讲透了!7天手把手带你写出专业级工具


1663

被折叠的 条评论
为什么被折叠?



