一、项目概述
1.1 项目简介
mymuduo 是一个基于 Reactor 模式的高性能 C++ 网络库,基于陈硕的 muduo 网络库进行 C++ 重构。它提供了简洁的 API,支持 TCP 服务器和客户端开发,具有以下特点:
- 事件驱动:基于 epoll 的高效 I/O 多路复用
- 多线程支持:主从 Reactor 模式,充分利用多核 CPU
- 异步编程:基于回调的异步编程模型
1.2 核心特性
| 特性 | 说明 |
|---|---|
| Reactor 模式 | 事件驱动的并发模型 |
| One Loop Per Thread | 每个线程一个事件循环 |
| 非阻塞 I/O | 全程非阻塞操作 |
| 连接管理 | 自动管理连接生命周期 |
| 缓冲区管理 | 高效的数据缓冲机制 |
| 日志系统 | 灵活的日志记录 |
1.3 项目结构
mymuduo/
├── include/ # 头文件目录
│ ├── EventLoop.h
│ ├── Channel.h
│ ├── Poller.h
│ ├── EPollPoller.h
│ ├── TcpServer.h
│ ├── TcpConnection.h
│ ├── Acceptor.h
│ ├── EventLoopThreadPool.h
│ ├── EventLoopThread.h
│ ├── Buffer.h
│ ├── Logger.h
│ ├── LogStream.h
│ ├── Thread.h
│ ├── Socket.h
│ ├── InetAddress.h
│ ├── Timestamp.h
│ ├── NonCopyable.h
│ ├── CurrentThread.h
│ └── Callbacks.h
├── src/ # 源文件目录
│ ├── EventLoop.cpp
│ ├── Channel.cpp
│ ├── Poller.cpp
│ ├── EPollPoller.cpp
│ ├── DefaultPoller.cpp
│ ├── TcpServer.cpp
│ ├── TcpConnection.cpp
│ ├── Acceptor.cpp
│ ├── EventLoopThreadPool.cpp
│ ├── EventLoopThread.cpp
│ ├── Logger.cpp
│ ├── LogStream.cpp
│ ├── Thread.cpp
│ ├── Socket.cpp
│ ├── InetAddress.cpp
│ ├── Timestamp.cpp
│ └── CurrentThread.cpp
├── example/ # 示例代码
│ └── EchoServer.cpp
├── readme/ # 文档目录
│ └── *.md
└── build/ # 构建目录
二、整体架构设计
2.1 架构总览
mymuduo 采用分层架构设计:
+--------------------------------------------------+
| 应用层 |
| (用户代码 / EchoServer) |
+--------------------------------------------------+
|
+--------------------------------------------------+
| 服务器层 |
| TcpServer / TcpConnection |
+--------------------------------------------------+
|
+--------------------------------------------------+
| 事件层 |
| EventLoop / Channel / Poller |
+--------------------------------------------------+
|
+--------------------------------------------------+
| 工具层 |
| Buffer / Logger / Thread / Socket / Timestamp |
+--------------------------------------------------+
2.2 Reactor 模式
mymuduo 实现了 Reactor 模式,核心组件包括:
+--------------------------------------------------+
| Reactor 模式 |
+--------------------------------------------------+
| |
| +-------------+ +-------------+ |
| | Handle |---->| Synchronous| |
| | (fd) | | Event Demux| |
| +-------------+ | (Poller) | |
| +-------------+ |
| | |
| v |
| +-------------+ |
| | Initiation | |
| | Dispatcher | |
| | (EventLoop)| |
| +-------------+ |
| | |
| v |
| +-------------+ |
| |Event Handler| |
| | (Channel) | |
| +-------------+ |
| | |
| v |
| +-------------+ |
| | Callbacks | |
| +-------------+ |
| |
+--------------------------------------------------+
2.3 主从 Reactor 线程模型
+--------------------------------------------------+
| 主从 Reactor 模型 |
+--------------------------------------------------+
| |
| +------------------+ |
| | mainReactor | (主线程) |
| | (baseLoop) | |
| +--------+---------+ |
| | |
| | 新连接 |
| v |
| +------------------+ |
| | Acceptor | |
| +--------+---------+ |
| | |
| | 分发连接 |
| v |
| +--------+--------+--------+--------+ |
| | | | | | |
| v v v v v |
| +----+ +----+ +----+ +----+ +----+ |
| |sub | |sub | |sub | |sub | |sub | |
| |Reactor|Reactor|Reactor|Reactor|Reactor| |
| +----+ +----+ +----+ +----+ +----+ |
| | | | | | |
| v v v v v |
| +----+ +----+ +----+ +----+ +----+ |
| |Conn| |Conn| |Conn| |Conn| |Conn| |
| +----+ +----+ +----+ +----+ +----+ |
| |
+--------------------------------------------------+
2.4 数据流向
接收数据流:
+----------+ +----------+ +----------+ +----------+
| Client |---->| socket |---->| Channel |---->| EventLoop|
+----------+ +----------+ +----------+ +----------+
|
v
+----------+ +----------+ +----------+ +----------+
| 用户回调 |<----|MessageCb |<----|inputBuffer|<---|handleRead|
+----------+ +----------+ +----------+ +----------+
发送数据流:
+----------+ +----------+ +----------+ +----------+
| 用户代码 |---->| send() |---->|outputBuffer|-->|handleWrite|
+----------+ +----------+ +----------+ +----------+
|
v
+----------+ +----------+ +----------+ +----------+
| Client |<----| socket |<----| Channel |<----| EventLoop|
+----------+ +----------+ +----------+ +----------+
三、技术选型
3.1 核心技术
| 技术 | 选择 | 原因 |
|---|---|---|
| I/O 多路复用 | epoll | Linux 高性能实现 |
| 线程模型 | std::thread | C++11 标准,跨平台 |
| 回调机制 | std::function | 类型安全,灵活 |
| 智能指针 | std::shared_ptr | 自动内存管理 |
| 原子操作 | std::atomic | 无锁编程支持 |
3.2 系统调用
| 系统调用 | 用途 |
|---|---|
| epoll_create1 | 创建 epoll 实例 |
| epoll_ctl | 控制 epoll 实例 |
| epoll_wait | 等待事件 |
| eventfd | 线程间通信 |
| accept4 | 接受连接 |
| readv | 分散读取 |
| sendfile | 零拷贝发送 |
3.3 设计模式
| 模式 | 应用场景 |
|---|---|
| Reactor | 事件驱动架构 |
| RAII | 资源管理 |
| 策略模式 | Poller 抽象 |
| 观察者模式 | 回调机制 |
| 工厂模式 | Poller 创建 |
四、模块职责与协作
4.1 核心模块
4.1.1 EventLoop
职责:
- 事件循环管理
- 任务调度
- 线程绑定
协作关系:
EventLoop
|
+-- Poller (I/O 多路复用)
|
+-- Channel (事件分发)
|
+-- wakeupFd (线程唤醒)
4.1.2 Channel
职责:
- 封装 fd 和事件
- 管理事件回调
- 事件状态跟踪
协作关系:
Channel
|
+-- EventLoop (所属循环)
|
+-- Poller (事件注册)
|
+-- TcpConnection (回调设置)
4.1.3 Poller / EPollPoller
职责:
- I/O 多路复用
- Channel 管理
- 事件轮询
协作关系:
Poller (抽象基类)
|
+-- EPollPoller (epoll 实现)
|
+-- ChannelMap (fd -> Channel)
4.1.4 TcpServer
职责:
- 服务器管理
- 连接管理
- 回调管理
协作关系:
TcpServer
|
+-- Acceptor (接受连接)
|
+-- EventLoopThreadPool (线程池)
|
+-- ConnectionMap (连接管理)
4.1.5 TcpConnection
职责:
- 连接状态管理
- 数据收发
- 事件处理
协作关系:
TcpConnection
|
+-- Socket (套接字)
|
+-- Channel (事件通道)
|
+-- Buffer (数据缓冲)
4.1.6 Acceptor
职责:
- 监听 socket 管理
- 接受新连接
- 回调通知
协作关系:
Acceptor
|
+-- Socket (监听 socket)
|
+-- Channel (监听事件)
|
+-- TcpServer (新连接回调)
4.1.7 EventLoopThreadPool
职责:
- 线程池管理
- 负载均衡
- EventLoop 分发
协作关系:
EventLoopThreadPool
|
+-- EventLoopThread[] (IO 线程)
|
+-- baseLoop (主循环)
4.1.8 Buffer
职责:
- 数据缓冲
- 高效读写
- 自动扩容
协作关系:
Buffer
|
+-- TcpConnection (输入/输出缓冲)
|
+-- readv (分散读取)
4.2 模块依赖图
+----------------+
| TcpServer |
+-------+--------+
|
+---------------+---------------+
| | |
+-------v-------+ +-----v-----+ +-------v-------+
| Acceptor | |Thread Pool| | ConnectionMap |
+-------+-------+ +-----+-----+ +-------+-------+
| | |
| | |
+-------v-------+ | +-------v-------+
| Socket | | | TcpConnection |
+-------+-------+ | +-------+-------+
| | |
v v v
+----------------+ +-----------+ +---------------+
| Channel | |EventLoop | | Buffer |
+----------------+ | Thread | | Socket |
| +-----------+ | Channel |
v | +---------------+
+----------------+ |
| EventLoop |<------+
+----------------+
|
v
+----------------+
| Poller |
+----------------+
五、项目使用
5.1 Echo 服务器示例
cpp
#include "TcpServer.h"
#include "EventLoop.h"
#include "LogStream.h"
#include <iostream>
using namespace mymuduo;
class EchoServer {
public:
EchoServer(EventLoop *loop, const InetAddress &addr, const std::string &name)
: server_(loop, addr, name), loop_(loop) {
server_.setConnectionCallback(
std::bind(&EchoServer::onConnection, this, std::placeholders::_1));
server_.setMessageCallback(
std::bind(&EchoServer::onMessage, this,
std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
server_.setThreadNum(3);
}
void start() { server_.start(); }
private:
void onConnection(const TcpConnectionPtr &conn) {
if (conn->connected()) {
LOG_INFO << "Connection UP : " << conn->peerAddress().toIpPort();
} else {
LOG_INFO << "Connection DOWN : " << conn->peerAddress().toIpPort();
}
}
void onMessage(const TcpConnectionPtr &conn, Buffer *buf, Timestamp time) {
std::string msg = buf->retrieveAllAsString();
conn->send(msg);
}
TcpServer server_;
EventLoop *loop_;
};
int main() {
g_logger = new Logger();
g_logger->SetLogLevel(kInfo);
EventLoop loop;
InetAddress addr(8080);
EchoServer server(&loop, addr, "EchoServer");
std::cout << "SERVER START..." << std::endl;
server.start();
loop.loop();
delete g_logger;
return 0;
}
5.2 使用流程
+--------------------------------------------------+
| 服务器使用流程 |
+--------------------------------------------------+
| |
| 1. 初始化日志系统 |
| g_logger = new Logger(); |
| g_logger->SetLogLevel(kInfo); |
| |
| 2. 创建事件循环 |
| EventLoop loop; |
| |
| 3. 创建服务器 |
| TcpServer server(&loop, addr, "name"); |
| |
| 4. 设置回调 |
| server.setConnectionCallback(...); |
| server.setMessageCallback(...); |
| |
| 5. 设置线程数 |
| server.setThreadNum(4); |
| |
| 6. 启动服务器 |
| server.start(); |
| |
| 7. 运行事件循环 |
| loop.loop(); |
| |
+--------------------------------------------------+
六、API 接口
6.1 TcpServer API
6.1.1 构造函数
cpp
TcpServer(EventLoop* loop,
const InetAddress& listenAddr,
const std::string& nameArg,
Option option = kNoReusePort);
参数说明:
| 参数 | 类型 | 说明 |
|---|---|---|
| loop | EventLoop* | 主事件循环 |
| listenAddr | const InetAddress& | 监听地址 |
| nameArg | const std::string& | 服务器名称 |
| option | Option | 端口重用选项 |
示例:
cpp
EventLoop loop;
InetAddress addr(8080, "0.0.0.0");
TcpServer server(&loop, addr, "MyServer");
6.1.2 设置回调
cpp
void setConnectionCallback(const ConnectionCallback& cb);
void setMessageCallback(const MessageCallback& cb);
void setWriteCompleteCallback(const WriteCompleteCallback& cb);
void setThreadInitCallback(const ThreadInitCallback& cb);
回调类型定义:
cpp
typedef std::function<void (const TcpConnectionPtr&)> ConnectionCallback;
typedef std::function<void (const TcpConnectionPtr&, Buffer*, Timestamp)> MessageCallback;
typedef std::function<void (const TcpConnectionPtr&)> WriteCompleteCallback;
typedef std::function<void(EventLoop*)> ThreadInitCallback;
6.1.3 启动服务器
cpp
void setThreadNum(int numThreads); // 设置线程数
void start(); // 启动服务器
6.2 TcpConnection API
6.2.1 基本信息
cpp
EventLoop* getLoop() const;
const std::string& name() const;
const InetAddress& localAddress() const;
const InetAddress& peerAddress() const;
bool connected() const;
6.2.2 数据发送
cpp
void send(const std::string &buf);
void sendFile(int fileDescriptor, off_t offset, size_t count);
void shutdown();
参数说明:
| 方法 | 说明 |
|---|---|
| send | 发送字符串数据 |
| sendFile | 零拷贝发送文件 |
| shutdown | 半关闭连接 |
6.2.3 回调设置
cpp
void setConnectionCallback(const ConnectionCallback &cb);
void setMessageCallback(const MessageCallback &cb);
void setWriteCompleteCallback(const WriteCompleteCallback &cb);
void setCloseCallback(const CloseCallback &cb);
void setHighWaterMarkCallback(const HighWaterMarkCallback &cb, size_t highWaterMark);
6.3 EventLoop API
6.3.1 事件循环控制
cpp
void loop(); // 启动事件循环
void quit(); // 退出事件循环
6.3.2 任务调度
cpp
void runInLoop(Functor cb); // 在事件循环中执行
void queueInLoop(Functor cb); // 加入任务队列
6.3.3 Channel 管理
cpp
void updateChannel(Channel* channel);
void removeChannel(Channel* channel);
bool hasChannel(Channel* channel);
6.4 Buffer API
6.4.1 数据读取
cpp
size_t readableBytes() const;
const char *peek() const;
void retrieve(size_t len);
void retrieveAll();
std::string retrieveAllAsString();
std::string retrieveAsString(size_t len);
6.4.2 数据写入
cpp
size_t writableBytes() const;
char *beginWrite();
void append(const char *data, size_t len);
6.4.3 I/O 操作
cpp
ssize_t readFd(int fd, int *saveErrno);
ssize_t writeFd(int fd, int *saveErrno);
6.5 InetAddress API
cpp
explicit InetAddress(uint16_t port = 0, std::string ip = "127.0.0.1");
std::string toIp() const;
std::string toIpPort() const;
uint16_t toPort() const;
const sockaddr_in *getSockAddr() const;
七、外部系统集成指南
7.1 HTTP 服务器集成
cpp
#include "TcpServer.h"
#include "EventLoop.h"
class HttpServer {
public:
HttpServer(EventLoop* loop, const InetAddress& addr)
: server_(loop, addr, "HttpServer") {
server_.setMessageCallback(
std::bind(&HttpServer::onRequest, this,
std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
}
private:
void onRequest(const TcpConnectionPtr& conn, Buffer* buf, Timestamp) {
// 解析 HTTP 请求
std::string request = buf->retrieveAllAsString();
// 生成 HTTP 响应
std::string response = "HTTP/1.1 200 OK\r\n"
"Content-Type: text/html\r\n"
"Content-Length: 13\r\n"
"\r\n"
"Hello, World!";
conn->send(response);
conn->shutdown();
}
TcpServer server_;
};
7.2 RPC 框架集成
cpp
class RpcServer {
public:
RpcServer(EventLoop* loop, const InetAddress& addr)
: server_(loop, addr, "RpcServer") {
server_.setMessageCallback(
std::bind(&RpcServer::onMessage, this,
std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
}
private:
void onMessage(const TcpConnectionPtr& conn, Buffer* buf, Timestamp) {
// 解析 RPC 请求
while (buf->readableBytes() >= 4) {
int32_t len = ntohl(*reinterpret_cast<const int32_t*>(buf->peek()));
if (buf->readableBytes() < 4 + len) break;
buf->retrieve(4);
std::string request(buf->peek(), len);
buf->retrieve(len);
// 处理 RPC 调用
std::string response = processRpc(request);
// 发送响应
int32_t respLen = htonl(response.size());
conn->send(std::string(reinterpret_cast<char*>(&respLen), 4) + response);
}
}
std::string processRpc(const std::string& request) {
// RPC 处理逻辑
return "result";
}
TcpServer server_;
};
7.3 消息队列集成
cpp
class MessageQueueBridge {
public:
MessageQueueBridge(TcpServer* server) : server_(server) {
server_->setMessageCallback(
std::bind(&MessageQueueBridge::onMessage, this,
std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
}
private:
void onMessage(const TcpConnectionPtr& conn, Buffer* buf, Timestamp) {
std::string msg = buf->retrieveAllAsString();
// 推送到消息队列
mq_.push(msg);
}
void processFromQueue() {
while (!mq_.empty()) {
std::string msg = mq_.pop();
// 处理消息
}
}
TcpServer* server_;
MessageQueue mq_;
};