在高并发网络编程中,传统的 “一连接一线程” 模型会因线程过多导致资源耗尽,而 Reactor 模式通过 “事件驱动 + IO 多路转接”,让单线程(或少量线程)高效处理数千甚至数万连接,成为 Nginx、Redis 等高性能中间件的核心架构。本文将以 “网络计算器” 为案例,从 Reactor 模式的核心思想入手,拆解 Connection 管理、事件分发、业务处理的完整流程,结合实战代码讲解如何基于 epoll 实现 Reactor 模式,帮你掌握高并发服务的设计精髓。
一、Reactor 模式核心认知:什么是反应堆?
Reactor 模式的本质是 “事件驱动的异步 IO 架构”,它通过一个 “反应堆”(Reactor 核心)统一管理所有 IO 事件,当事件就绪时(如 socket 可读、可写),自动分发到对应的业务处理逻辑,避免主动轮询或线程阻塞。
1.1 核心思想:“反向调用”
传统 IO 模型中,应用程序主动调用 IO 函数(如read/write)并阻塞等待;Reactor 模式则相反:
应用程序将 “IO 事件” 和 “处理逻辑” 注册到 Reactor;
Reactor 通过 IO 多路转接(如 epoll)监控事件;
事件就绪时,Reactor 主动调用注册的处理逻辑(回调函数),即 “反向调用”。
1.2 关键组件
一个完整的 Reactor 架构包含 4 个核心组件,协同实现事件驱动:
| 组件 | 功能 | 示例(本文实现) |
|---|---|---|
| Reactor 核心 | 管理 IO 多路转接(epoll),监控事件,分发事件到处理器 | TcpServer类(封装 epoll 操作) |
| 事件处理器 | 注册事件和回调函数,处理具体 IO 事件(如读、写、异常) | HandlerConnection类(处理读写逻辑) |
| 连接管理器 | 管理客户端连接(创建、销毁、存储),维护连接的缓冲区和状态 | Connection类(封装 socket、缓冲区、回调) |
| ** acceptor** | 处理新连接请求(监听 socket 的可读事件),创建新连接并注册到 Reactor | Accepter类(accept 新连接,初始化 Connection) |
二、Reactor 模式工作流程:事件驱动的完整闭环
Reactor 模式的工作流程可概括为 “注册事件→监控事件→分发事件→处理事件”,以 “网络计算器” 为例,完整流程如下:
- 初始化 Reactor:创建 epoll 实例,初始化监听 socket,将 “监听事件(EPOLLIN)” 和 “新连接处理逻辑” 注册到 Reactor;
- 等待事件就绪:Reactor 调用
epoll_wait,阻塞等待事件(如新连接请求、客户端数据到达); - 新连接处理:
- 监听 socket 就绪,
Accepter调用accept创建新 socket,设置为非阻塞; - 创建
Connection对象(封装新 socket、缓冲区、回调函数),将 “读事件(EPOLLIN|EPOLLET)” 注册到 epoll;
- 监听 socket 就绪,
- 客户端数据处理:
- 客户端 socket 可读,Reactor 触发 “读回调”,读取数据到
Connection的输入缓冲区; - 解析输入缓冲区中的完整协议报文(解粘包),调用业务逻辑(计算表达式);
- 将计算结果写入
Connection的输出缓冲区,注册 “写事件(EPOLLOUT)”;
- 客户端 socket 可读,Reactor 触发 “读回调”,读取数据到
- 结果发送:
- 客户端 socket 可写,Reactor 触发 “写回调”,将输出缓冲区数据发送给客户端;
- 若数据发送完毕,取消写事件注册;若未发送完,保留写事件监听;
- 异常处理:若连接出错(如客户端关闭),触发 “异常回调”,销毁
Connection并从 epoll 中移除。
三、核心组件设计与实现
基于 Reactor 模式,我们将系统拆分为Connection(连接封装)、Accepter(新连接处理)、HandlerConnection(业务逻辑)、TcpServer(Reactor 核心)四个组件,以下逐一讲解设计细节。
3.1 Connection:连接的 “全能封装器”
Connection类是 Reactor 模式的 “最小业务单元”,它封装了 socket、输入 / 输出缓冲区、事件状态和回调函数,统一管理单个连接的生命周期。
3.1.1 核心功能
封装 socket 文件描述符,管理连接的打开与关闭;
维护输入缓冲区(_inbuffer)和输出缓冲区(_outbuffer),处理数据的接收与发送;
注册回调函数(读、写、异常),关联业务处理逻辑;
记录连接的事件状态(如关心的 epoll 事件)和客户端地址(IP + 端口)。
3.1.2 实战代码(Connection.hpp)
#pragma once
#include <iostream>
#include <string>
#include <functional>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
// 前向声明,避免循环引用
class TcpServer;
// 回调函数类型:接收、发送、异常处理(参数为Connection指针)
using func_t = std::function<void(Connection*)>;
class Connection {
public:
// 构造:初始化socket、关心的事件、关联的TcpServer
Connection(int sockfd, uint32_t events, TcpServer* reactor)
: _sockfd(sockfd), _events(events), _R(reactor) {}
// 注册回调函数(读、写、异常)
void RegisterCallback(func_t recver, func_t sender, func_t excepter) {
_recver = recver;
_sender = sender;
_excepter = excepter;
}
// 输入缓冲区操作:追加数据(接收数据时用)
void AddInBuffer(const std::string& buffer) {
_inbuffer += buffer;
}
// 输出缓冲区操作:追加数据(发送数据时用)
void AddOutBuffer(const std::string& buffer) {
_outbuffer += buffer;
}
// 检查输出缓冲区是否为空(判断是否需要注册写事件)
bool OutBufferEmpty() const {
return _outbuffer.empty();
}
// 获取socket文件描述符(供epoll操作)
int SockFd() const {
return _sockfd;
}
// 获取/设置关心的epoll事件(如EPOLLIN、EPOLLOUT)
uint32_t Events() const {
return _events;
}
void SetEvents(uint32_t events) {
_events = events;
}
// 设置客户端地址(IP+端口)
void SetClient(const struct sockaddr_in& client) {
_client = client;
}
// 获取输入/输出缓冲区(供业务逻辑读写)
std::string& InBuffer() {
return _inbuffer;
}
std::string& OutBuffer() {
return _outbuffer;
}
// 关闭连接(释放socket)
void Close() {
::close(_sockfd);
}
~Connection() = default;
public:
// 回调函数:由HandlerConnection实现
func_t _recver; // 读事件回调
func_t _sender; // 写事件回调
func_t _excepter; // 异常事件回调
TcpServer* _R; // 回指Reactor核心(TcpServer),用于操作epoll
private:
int _sockfd; // 连接对应的socket文件描述符
std::string _inbuffer; // 输入缓冲区(存储客户端发送的数据)
std::string _outbuffer; // 输出缓冲区(存储待发送给客户端的数据)
uint32_t _events; // 关心的epoll事件(如EPOLLIN|EPOLLET)
struct sockaddr_in _client; // 客户端地址(IP+端口)
};
// Connection工厂类:统一创建连接(工厂模式,简化对象创建)
class ConnectionFactory {
public:
// 创建监听连接(监听socket专用)
static Connection* BuildListenConnection(int listensock, func_t recver, uint32_t events, TcpServer* reactor) {
Connection* conn = new Connection(listensock, events, reactor);
conn->RegisterCallback(recver, nullptr, nullptr); // 监听连接仅需读回调
return conn;
}
// 创建普通客户端连接(新连接专用)
static Connection* BuildNormalConnection(int sockfd, func_t recver, func_t sender, func_t excepter, uint32_t events, TcpServer* reactor) {
Connection* conn = new Connection(sockfd, events, reactor);
conn->RegisterCallback(recver, sender, excepter); // 普通连接需读、写、异常回调
return conn;
}
};
3.2 Accepter:新连接的 “守门人”
Accepter类专门处理 “新连接请求”—— 当监听 socket(listensock)可读时,它通过accept创建新 socket,初始化Connection并注册到 Reactor,是连接进入系统的 “入口”。
3.2.1 核心逻辑
监听 socket 就绪时,Accepter循环调用accept(非阻塞模式,避免漏接连接);
新 socket 设置为非阻塞(配合 epoll 的 ET 模式);
通过ConnectionFactory创建普通连接,注册 “读回调、写回调、异常回调”;
将新连接添加到 Reactor 的连接管理列表,并注册读事件到 epoll。
3.2.2 实战代码(Accepter.hpp)
#pragma once
#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <cerrno>
#include "Connection.hpp"
#include "HandlerConnection.hpp"
#include "Log.hpp" // 简化日志,可自行实现
// 设置socket为非阻塞(ET模式必需)
void SetNonBlock(int sockfd) {
int fl = fcntl(sockfd, F_GETFL);
if (fl < 0) {
perror("fcntl F_GETFL");
return;
}
fcntl(sockfd, F_SETFL, fl | O_NONBLOCK);
}
class Accepter {
public:
// 处理新连接(参数为监听连接的Connection)
void AccepterConnection(Connection* listen_conn) {
errno = 0;
// 循环accept,避免漏接(ET模式下监听socket可读可能有多个连接)
while (true) {
struct sockaddr_in client_addr;
socklen_t client_len = sizeof(client_addr);
// 非阻塞accept(因listensock已设为非阻塞)
int new_sockfd = ::accept(listen_conn->SockFd(), (struct sockaddr*)&client_addr, &client_len);
if (new_sockfd > 0) {
lg.LogMessage(Info, "new connection accepted, sockfd: %d", new_sockfd);
// 1. 设置新socket为非阻塞
SetNonBlock(new_sockfd);
// 2. 绑定业务回调(读、写、异常由HandlerConnection实现)
auto recver = std::bind(&HandlerConnection::Recver, std::placeholders::_1);
auto sender = std::bind(&HandlerConnection::Sender, std::placeholders::_1);
auto excepter = std::bind(&HandlerConnection::Excepter, std::placeholders::_1);
// 3. 创建普通连接(ET模式,关心读事件)
Connection* new_conn = ConnectionFactory::BuildNormalConnection(
new_sockfd, recver, sender, excepter, EPOLLIN | EPOLLET, listen_conn->_R
);
new_conn->SetClient(client_addr); // 记录客户端地址
// 4. 将新连接添加到Reactor(注册epoll事件)
listen_conn->_R->AddConnection(new_conn);
} else {
// 处理accept错误:EAGAIN表示无更多连接,EINTR表示被信号中断
if (errno == EAGAIN) break; // 正常退出循环
else if (errno == EINTR) continue; // 重试
else {
lg.LogMessage(Warning, "accept failed, errno: %d", errno);
break;
}
}
}
}
~Accepter() = default;
};
3.3 HandlerConnection:业务逻辑的 “执行者”
HandlerConnection类是 Reactor 模式的 “业务处理中心”,它实现了 “读、写、异常” 三大回调函数,负责将 IO 事件转化为具体业务逻辑(如解析协议、计算表达式、发送结果)。
3.3.1 核心功能
- Recver(读回调):从 socket 读取数据到输入缓冲区,调用
HandlerRequest解析协议并处理业务; - Sender(写回调):将输出缓冲区数据发送到 socket,根据发送结果决定是否保留写事件;
- Excepter(异常回调):处理连接异常(如客户端关闭),销毁连接并从 Reactor 中移除;
- HandlerRequest(业务处理):解析输入缓冲区中的完整协议报文,调用计算器业务,生成响应并写入输出缓冲区。
3.3.2 依赖组件
Protocol:自定义应用层协议(参考前文 “应用层自定义协议”,实现Encode/Decode解粘包);
Calculate:网络计算器业务类(实现表达式计算,如 “1+1”→“2”)。
3.3.3 实战代码(HandlerConnection.hpp)
#pragma once
#include <iostream>
#include <cerrno>
#include <string>
#include "Connection.hpp"
#include "Protocol.hpp" // 自定义协议:Encode/Decode解粘包
#include "Calculate.hpp" // 计算器业务:处理表达式计算
#include "Log.hpp"
using namespace Protocol; // 协议相关函数(Encode/Decode)
using namespace CalculateNS; // 计算器相关类(Calculate)
const static int BUFFER_SIZE = 1024; // 读取缓冲区大小
class HandlerConnection {
public:
// 业务处理核心:解析协议,计算结果,生成响应
static void HandlerRequest(Connection* conn) {
std::string& inbuffer = conn->InBuffer();
std::string message; // 存储单个完整协议报文
// 1. 解粘包:从输入缓冲区提取完整报文(循环处理所有完整报文)
while (Decode(inbuffer, &message)) {
// 2. 反序列化:JSON字符串→Request结构体(操作数+运算符)
Factory proto_factory; // 协议工厂(创建Request/Response)
auto req = proto_factory.BuildRequest();
if (!req->Deserialize(message)) {
lg.LogMessage(Error, "request deserialize failed");
continue;
}
// 3. 业务计算:调用计算器处理表达式
Calculate calculator;
auto resp = calculator.Cal(req); // resp包含计算结果和状态码
// 4. 序列化:Response结构体→JSON字符串
std::string resp_json;
resp->Serialize(&resp_json);
// 5. 封装协议:添加长度前缀(避免粘包)
std::string resp_package = Encode(resp_json);
// 6. 写入输出缓冲区,等待发送
conn->AddOutBuffer(resp_package);
}
// 7. 触发写事件:若输出缓冲区非空,立即调用写回调发送数据
if (!conn->OutBufferEmpty()) {
conn->_sender(conn);
}
}
// 读回调:从socket读取数据到输入缓冲区
static void Recver(Connection* conn) {
errno = 0;
char buffer[BUFFER_SIZE];
// 非阻塞循环读取(ET模式需一次读完缓冲区数据)
while (true) {
ssize_t n = recv(conn->SockFd(), buffer, sizeof(buffer) - 1, 0);
if (n > 0) {
buffer[n] = '\0';
conn->AddInBuffer(buffer); // 追加到输入缓冲区
} else {
// 处理读错误:EAGAIN表示缓冲区空,EINTR表示被信号中断
if (errno == EAGAIN) break; // 正常退出,已读完
else if (errno == EINTR) continue; // 重试
else {
// 严重错误:触发异常回调,销毁连接
lg.LogMessage(Error, "recv failed, sockfd: %d, errno: %d", conn->SockFd(), errno);
conn->_excepter(conn);
return;
}
}
}
// 打印调试信息(可选)
lg.LogMessage(Debug, "sockfd: %d, inbuffer: %s", conn->SockFd(), conn->InBuffer().c_str());
// 调用业务处理逻辑
HandlerRequest(conn);
}
// 写回调:将输出缓冲区数据发送到socket
static void Sender(Connection* conn) {
errno = 0;
std::string& outbuffer = conn->OutBuffer();
// 非阻塞循环发送(ET模式需一次发完缓冲区数据)
while (true) {
ssize_t n = send(conn->SockFd(), outbuffer.c_str(), outbuffer.size(), 0);
if (n >= 0) {
outbuffer.erase(0, n); // 移除已发送的数据
if (outbuffer.empty()) break; // 数据发送完毕,退出
} else {
// 处理写错误:EAGAIN表示发送缓冲区满,EINTR表示被信号中断
if (errno == EAGAIN) break; // 正常退出,后续再发
else if (errno == EINTR) continue; // 重试
else {
// 严重错误:触发异常回调
lg.LogMessage(Error, "send failed, sockfd: %d, errno: %d", conn->SockFd(), errno);
conn->_excepter(conn);
return;
}
}
}
// 调整epoll事件:若数据未发完,保留写事件;否则取消写事件
if (!conn->OutBufferEmpty()) {
// 仍有数据待发,开启读+写事件监听
conn->_R->EnableReadWrite(conn->SockFd(), true, true);
} else {
// 数据发完,仅保留读事件监听
conn->_R->EnableReadWrite(conn->SockFd(), true, false);
}
}
// 异常回调:处理连接异常,销毁连接
static void Excepter(Connection* conn) {
lg.LogMessage(Info, "connection closed, sockfd: %d", conn->SockFd());
// 1. 从Reactor中移除连接(删除epoll事件+删除连接列表)
conn->_R->RemoveConnection(conn->SockFd());
// 2. 关闭socket
conn->Close();
// 3. 释放Connection对象
delete conn;
}
};
3.4 TcpServer:Reactor 核心的 “大脑”
TcpServer类是 Reactor 模式的 “控制中心”,它封装了 epoll 操作(创建、注册事件、等待事件),管理所有连接,实现事件分发,是整个架构的 “大脑”。
3.4.1 核心功能
初始化 epoll 实例和监听 socket;
管理连接列表(存储Connection,支持添加、删除、查找);
注册 / 取消 epoll 事件,控制事件监听(如开启 / 关闭读、写事件);
事件循环:调用epoll_wait等待事件,分发事件到对应的回调函数。
3.4.2 实战代码(TcpServer.hpp)
#pragma once
#include <iostream>
#include <unordered_map>
#include <vector>
#include <sys/epoll.h>
#include <netinet/in.h>
#include "Connection.hpp"
#include "Accepter.hpp"
#include "Log.hpp"
class TcpServer {
public:
TcpServer(uint16_t port) : _port(port), _epfd(-1), _listensock(-1) {}
// 初始化Reactor:创建epoll、监听socket、注册监听事件
bool Init() {
// 1. 创建epoll实例
_epfd = epoll_create(10); // size参数已忽略,传任意正数
if (_epfd < 0) {
perror("epoll_create");
return false;
}
// 2. 创建监听socket
_listensock = socket(AF_INET, SOCK_STREAM, 0);
if (_listensock < 0) {
perror("socket");
close(_epfd);
return false;
}
// 3. 设置监听socket为非阻塞(ET模式)
SetNonBlock(_listensock);
// 4. 绑定端口
struct sockaddr_in local_addr;
memset(&local_addr, 0, sizeof(local_addr));
local_addr.sin_family = AF_INET;
local_addr.sin_port = htons(_port);
local_addr.sin_addr.s_addr = htonl(INADDR_ANY); // 绑定所有网卡IP
if (bind(_listensock, (struct sockaddr*)&local_addr, sizeof(local_addr)) < 0) {
perror("bind");
close(_listensock);
close(_epfd);
return false;
}
// 5. 监听
if (listen(_listensock, 5) < 0) {
perror("listen");
close(_listensock);
close(_epfd);
return false;
}
// 6. 创建监听连接,注册“新连接处理回调”
auto accept_cb = std::bind(&Accepter::AccepterConnection, &_accepter, std::placeholders::_1);
_listen_conn = ConnectionFactory::BuildListenConnection(
_listensock, accept_cb, EPOLLIN | EPOLLET, this
);
// 7. 将监听连接注册到epoll
AddConnection(_listen_conn);
lg.LogMessage(Info, "Reactor server init success, port: %d, epfd: %d", _port, _epfd);
return true;
}
// 启动Reactor事件循环
void Start() {
struct epoll_event events[1000]; // 就绪事件数组(支持1000个并发连接)
while (true) {
// 等待事件就绪(永久阻塞,直到有事件)
int nfds = epoll_wait(_epfd, events, sizeof(events)/sizeof(events[0]), -1);
if (nfds < 0) {
perror("epoll_wait");
continue;
}
// 遍历就绪事件,分发到对应的回调函数
for (int i = 0; i < nfds; ++i) {
int sockfd = events[i].data.fd;
uint32_t revents = events[i].events; // 就绪的事件类型
// 查找对应的Connection
auto it = _conn_map.find(sockfd);
if (it == _conn_map.end()) {
lg.LogMessage(Warning, "unknown sockfd: %d", sockfd);
continue;
}
Connection* conn = it->second;
// 处理就绪事件:读、写、异常
if (revents & (EPOLLIN | EPOLLPRI)) {
// 读事件就绪(普通数据或紧急数据)
conn->_recver(conn);
}
if (revents & EPOLLOUT) {
// 写事件就绪
conn->_sender(conn);
}
if (revents & (EPOLLERR | EPOLLHUP)) {
// 异常事件(错误或连接挂断)
conn->_excepter(conn);
}
}
}
}
// 添加连接到Reactor(注册epoll事件+加入连接列表)
void AddConnection(Connection* conn) {
int sockfd = conn->SockFd();
uint32_t events = conn->Events();
// 1. 注册epoll事件
struct epoll_event ev;
ev.events = events;
ev.data.fd = sockfd;
if (epoll_ctl(_epfd, EPOLL_CTL_ADD, sockfd, &ev) < 0) {
perror("epoll_ctl ADD");
return;
}
// 2. 加入连接列表
_conn_map.emplace(sockfd, conn);
lg.LogMessage(Debug, "connection added, sockfd: %d, total conn: %lu", sockfd, _conn_map.size());
}
// 从Reactor移除连接(删除epoll事件+删除连接列表)
void RemoveConnection(int sockfd) {
// 1. 从epoll中删除事件
if (epoll_ctl(_epfd, EPOLL_CTL_DEL, sockfd, nullptr) < 0) {
perror("epoll_ctl DEL");
return;
}
// 2. 从连接列表中删除
_conn_map.erase(sockfd);
lg.LogMessage(Debug, "connection removed, sockfd: %d, total conn: %lu", sockfd, _conn_map.size());
}
// 开启/关闭读、写事件监听(动态调整epoll事件)
void EnableReadWrite(int sockfd, bool enable_read, bool enable_write) {
auto it = _conn_map.find(sockfd);
if (it == _conn_map.end()) {
lg.LogMessage(Warning, "EnableReadWrite: unknown sockfd: %d", sockfd);
return;
}
Connection* conn = it->second;
// 计算新的事件类型
uint32_t new_events = 0;
if (enable_read) new_events |= EPOLLIN | EPOLLET;
if (enable_write) new_events |= EPOLLOUT | EPOLLET;
conn->SetEvents(new_events);
// 更新epoll事件
struct epoll_event ev;
ev.events = new_events;
ev.data.fd = sockfd;
if (epoll_ctl(_epfd, EPOLL_CTL_MOD, sockfd, &ev) < 0) {
perror("epoll_ctl MOD");
return;
}
}
~TcpServer() {
if (_listensock != -1) close(_listensock);
if (_epfd != -1) close(_epfd);
// 释放所有连接
for (auto& [sockfd, conn] : _conn_map) {
conn->Close();
delete conn;
}
}
private:
uint16_t _port; // 服务端口
int _epfd; // epoll实例句柄
int _listensock; // 监听socket
Connection* _listen_conn; // 监听连接的Connection
Accepter _accepter; // 新连接处理器
std::unordered_map<int, Connection*> _conn_map; // 连接列表(sockfd→Connection)
};
四、Reactor 模式完整运行流程
结合上述组件,“网络计算器” 的完整运行流程如下,清晰展现 Reactor 的事件驱动逻辑:
-
启动服务:
- 创建
TcpServer实例,调用Init()初始化 epoll、监听 socket、注册监听连接; - 调用
Start()进入事件循环,epoll_wait阻塞等待事件。
- 创建
-
新连接请求:
- 客户端发起连接,监听 socket 可读,
epoll_wait返回; - Reactor 分发读事件到
Accepter的AccepterConnection; Accepter调用accept创建新 socket,初始化Connection并注册到 Reactor。
- 客户端发起连接,监听 socket 可读,
-
客户端发送计算请求:
- 客户端发送 “1+1”,新 socket 可读,
epoll_wait返回; - Reactor 分发读事件到
HandlerConnection的Recver; Recver读取数据到输入缓冲区,调用HandlerRequest解析协议、计算结果、写入输出缓冲区;- 调用
Sender发送结果,若发送完毕,取消写事件。
- 客户端发送 “1+1”,新 socket 可读,
-
客户端关闭连接:
- 客户端关闭 socket,新 socket 触发
EPOLLHUP事件; - Reactor 分发异常事件到
HandlerConnection的Excepter; Excepter销毁Connection,从 Reactor 中移除连接。
- 客户端关闭 socket,新 socket 触发
五、Reactor 模式的优势与适用场景
5.1 核心优势
- 高并发支持:单线程(或少量线程)处理数万连接,避免线程切换开销;
- 低资源消耗:无需为每个连接创建线程,内存和 CPU 资源占用低;
- 异步非阻塞:IO 操作非阻塞,事件驱动无主动等待,资源利用率高;
- 扩展性强:业务逻辑与 IO 事件解耦,新增业务只需实现新的回调函数。
5.2 适用场景
高并发、低数据量:如聊天服务器、API 网关、物联网设备通信(连接多但单连接数据量小);
IO 密集型服务:如 Nginx(Web 服务器)、Redis(缓存)、Memcached(分布式缓存);
不适用 CPU 密集型:若业务逻辑耗时过长(如复杂计算),会阻塞 Reactor 线程,需配合线程池(Proactor 模式)。
六、总结与扩展
本文通过 “网络计算器” 案例,完整实现了基于 epoll 的 Reactor 模式,核心收获包括:
- 架构设计:理解 Reactor 模式的 “事件驱动 + 反向调用” 思想,掌握四大组件的协同逻辑;
- 代码实战:学会封装 Connection 管理连接状态,用 epoll 实现事件监控与分发,通过回调函数解耦 IO 与业务;
- 高并发要点:ET 模式配合非阻塞 IO,确保一次处理完缓冲区数据;动态调整 epoll 事件,避免无效监听。
扩展方向
- 多线程 Reactor:单 Reactor 负责事件分发,业务逻辑交给线程池处理,解决 CPU 密集型业务阻塞问题;
- 主从 Reactor:主 Reactor 处理新连接,从 Reactor 处理已连接的 IO 事件,进一步提升并发能力(如 Nginx 架构);
- Proactor 模式:Reactor 是 “同步 IO + 事件驱动”,Proactor 是 “异步 IO + 事件驱动”,适合 Windows(IOCP)或 Linux(io_uring)。
329

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



