目录
[1. 事件源定义](#1. 事件源定义)
[2. 事件处理器接口(EventHandler)](#2. 事件处理器接口(EventHandler))
[3. 事件多路分发器接口(EventDemultiplexer)](#3. 事件多路分发器接口(EventDemultiplexer))
[4. Reactor 核心类(Reactor)](#4. Reactor 核心类(Reactor))
一、Reactor模式的由来
在网络通信中,我们已经学过了使用epoll模型来帮助我们完成高并发场景下的网络通信问题,但是在使用epoll_wait后,就会发现有两种写法:第一种是以FD的类型为主要判断条件,第二类是以触发事件的类型为主要判断条件。在简单的场景中,二者都是完全合理的,但是人们发现随着代码的复杂度提高,第一种写法的臃肿程度逐渐变高,代码也不利于维护。这是因为,每次多增添一种FD类型,就要在里面插入一个if、else代码块;而在第二种场景下,由于事件始终只有那么几种:读、写、错误等。再多的FD类型也只是在这几个有限的if、else代码块中插入扩展。
我们把这种第一判断条件为事件类型的方式称为反应堆模式,本质上是把直观的思维模式,升级成更加抽象的事件驱动思维,用一种框架解决了稳定点和变化点的问题。于是逐渐成为了一种设计模式---Reactor模式。
Reactor 模式是一种事件驱动(Event-Driven)设计模式,它的核心是通过一个 "事件循环" 不断监听事件,当事件发生时自动调用对应的处理逻辑。这种模式特别适合处理多个并发事件源,能高效地将事件与处理逻辑解耦。
二、Reactor模式的核心组件及工作流程
Reactor模式的本质是"组件化的事件处理框架",其核心能力依赖于4个紧密协作的组件,我们用智能家居系统来类比,解释各个组件的作用:
事件源(Event Source):
产生事件的实体,是事件的源头。好比智能家居的传感器,对于环境温度变化产生事件
事件多路分发器(Event Demultiplexer):
监控多个事件源,等待事件发生并收集就绪事件的"监听器"。比如智能家居的中控器,当各个传感器产生事件的时候,会把事件告诉中控器。虽然他叫分发器,但是并不执行分发模块,仅仅是监控,类似于IO多路复用。
事件处理器:
定义事件处理接口,包含具体的业务逻辑。比如空调控制器、点灯控制器。中央控制器把事件按照类别分别发送给这些处理模块。
Reactor核心:
协调各个组件的总指挥,负责事件注册,事件分发,以及驱动事件循环。即提供一个运行框架,让上述三个组件能在框架中配合使用。注意:他还有个核心功能是分发事件。
组件协作工作流程:
(1)事件源被注册到Reactor核心,把某类事件关联到对应的事件处理器。
(2)Reactor核心将事件源移交给事件多路分发器监控。
(3)事件多路分发器等待事件发生。
(4)事件发生后,分发器将就绪事件返还给Reactor核心。
(5)Reactor核心根据事件源找到对应的处理器,调用事件处理逻辑。

三、基础Reactor模式的接口设计
为了让框架具备通用性和可扩展性,我们先抽象出核心接口。接口设计遵循依赖倒置原则:高层模块(Reactor 核心)依赖抽象接口,而非具体实现。
1. 事件源定义
首先定义事件的 "类型标识",用于区分不同事件(如可读、可写):
cpp
// 事件类型枚举(基础版)
enum class EventType {
EVENT_READ, // 可读事件(数据到达、新连接等)
EVENT_WRITE // 可写事件(缓冲区空闲,可发送数据)
};
当然仅仅只有类型定义远远不够,需要有一个连接类对其封装。我们也把这个连接类称为事件源。
这个类是对fd的封装,当我们使用accept的时候,会得到一个新的文件描述符fd,为了将回调函数抽离出来后方便调用,而不是依赖于传参,我们把这个fd封装到一个类中。同时由于各个文件的缓冲区希望是独立的,否则会出现数据混淆(尤其是在并发场景下)。所以我们设计了两个收、发两个缓冲区。
这个类和处理器类有着紧密联系,一般情况下设计会让他们互相持有对方的指针。即连接类可以通过指针访问到处理器中的回调函数。而处理器在使用回调函数的时候也能方便地通过Connection类得到其fd及缓冲区等字段。
cpp
//5.连接类组件:负责管理fd、收发缓冲区等
class Connection
{
private:
int _fd=-1;
std::vector<char> _recvBuffer;
std::vector<char> _sendBuffer;
EventType _type;
public:
//构造函数
explicit Connection(int fd)
:_fd(fd)
{
_recvBuffer.reserve(1024);
_sendBuffer.reserve(1024);
}
//析构函数
~Connection()
{
if(_fd!=-1)
{
close(_fd);
_fd=-1;
}
}
//让处理器获取fd
int getfd()
{
return _fd;
}
//获取读缓冲区
std::vector<char>& get_recvBuffer()
{
return _recvBuffer;
}
//获取写缓冲区
std::vector<char>& get_sendBuffer()
{
return _sendBuffer;
}
};
2. 事件处理器接口(EventHandler)
所有具体的事件处理器都需实现此接口,定义 "处理什么事件" 和 "关联哪个事件源":
cpp
// 事件处理器接口:封装事件处理逻辑
class EventHandler {
public:
// 纯虚函数:处理事件的核心逻辑
// 参数:事件源的文件描述符、事件类型
virtual void handleEvent(int fd, EventType type) = 0;
// 纯虚函数:获取当前处理器关联的事件源fd
// 作用:Reactor通过fd找到对应的处理器
virtual int getFd() const = 0;
// 虚析构函数:确保子类析构函数被正确调用
virtual ~EventHandler() = default;
};
接口设计理由:
- 用
handleEvent
统一处理入口,无论处理文件还是网络事件,都通过此方法触发; - 用
getFd
绑定事件源,Reactor 通过 fd 建立 "事件源 - 处理器" 的映射关系。
3. 事件多路分发器接口(EventDemultiplexer)
cpp
#include <vector>
#include <utility> // 用于std::pair
// 事件多路分发器接口:定义事件监控、注册、移除的规范
class EventDemultiplexer {
public:
// 等待事件就绪
// 参数:timeout-超时时间(秒);activeEvents-输出参数,存储就绪事件(fd, 事件类型)
// 返回值:就绪事件数量,-1表示错误
virtual int waitEvents(int timeout, std::vector<std::pair<int, EventType>>& activeEvents) = 0;
// 注册事件:将fd和事件类型加入监控
virtual void registerEvent(int fd, EventType type) = 0;
// 移除事件:停止监控fd的指定事件类型
virtual void removeEvent(int fd, EventType type) = 0;
virtual ~EventDemultiplexer() = default;
};
接口设计理由:
waitEvents
是核心方法,负责阻塞等待事件,返回后 Reactor 即可获取就绪事件;registerEvent
和removeEvent
支持动态添加 / 移除事件源,适应场景变化(如客户端连接 / 断开)。
4. Reactor 核心类(Reactor)
协调事件注册、分发和循环的核心控制器:
cpp
#include <map>
#include <memory> // 可选,用于管理指针
// Reactor核心类:事件驱动的总控制器
class Reactor {
private:
EventDemultiplexer* demultiplexer; // 事件分发器(依赖注入)
std::map<int, EventHandler*> handlers; // fd到处理器的映射表(核心映射)
public:
// 构造函数:传入具体的事件分发器(依赖注入,方便替换select/epoll)
explicit Reactor(EventDemultiplexer* demux) : demultiplexer(demux) {}
// 注册事件:将事件源、事件类型与处理器关联
void registerHandler(EventHandler* handler, EventType type) {
int fd = handler->getFd();
handlers[fd] = handler; // 记录fd与处理器的映射
demultiplexer->registerEvent(fd, type); // 通知分发器开始监控
}
// 移除事件:停止监控并解除映射
void removeHandler(EventHandler* handler, EventType type) {
int fd = handler->getFd();
demultiplexer->removeEvent(fd, type); // 通知分发器停止监控
handlers.erase(fd); // 移除映射关系
}
// 事件循环:Reactor的核心运行逻辑
void eventLoop() {
while (true) { // 无限循环,持续处理事件
std::vector<std::pair<int, EventType>> activeEvents; // 存储就绪事件
// 等待事件就绪(超时1秒,避免永久阻塞)
int n = demultiplexer->waitEvents(1, activeEvents);
if (n < 0) { // 错误处理
perror("waitEvents error");
break;
} else if (n == 0) { // 超时,无事件就绪
continue;
}
// 遍历所有就绪事件,调用对应处理器处理
for (const auto& [fd, type] : activeEvents) {
auto it = handlers.find(fd);
if (it != handlers.end()) { // 确保处理器存在
it->second->handleEvent(fd, type); // 分发事件给处理器
}
}
}
}
};
核心逻辑解析:
handlers
映射表是 Reactor 的 "大脑",通过 fd 快速找到对应的处理器;eventLoop
是 "心脏",不断循环等待事件→收集事件→分发事件,构成事件驱动的核心流程。
四、示例代码
cpp
#include <sys/epoll.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <errno.h>
#include <cstring>
#include <vector>
#include <map>
#include <memory>
#include <functional>
#include <iostream>
#include <chrono>
#include <ctime>
// 事件类型枚举
enum class EventType
{
EVENT_READ = EPOLLIN,
EVENT_WRITE = EPOLLOUT,
EVENT_ERROR = EPOLLERR
};
// 事件触发模式
enum class TriggerMode
{
LEVEL_TRIGGER,
EDGE_TRIGGER
};
// 前向声明
class Reactor;
// 工具函数:获取当前时间字符串(用于日志)
std::string getCurrentTime() {
auto now = std::chrono::system_clock::now();
std::time_t now_time = std::chrono::system_clock::to_time_t(now);
return std::ctime(&now_time);
}
// 1. 连接管理类
class Connection
{
private:
int _fd;
std::vector<char> _recvBuffer;
std::vector<char> _sendBuffer;
TriggerMode _triggerMode;
public:
// 读取数据到缓冲区
ssize_t readData()
{
char buffer[1024];
ssize_t n;
ssize_t total = 0;
//因为有可能设置为边沿触发,所以有可能一次性读不完。需要循环读。
//即使为水平触发,没读完会多次通知事件就绪,但是也导致了重复唤醒的开销。所以无论ET、LT都要用循环读
while (true)
{
n = read(_fd, buffer, sizeof(buffer));
if (n > 0)
{
_recvBuffer.insert(_recvBuffer.end(), buffer, buffer + n);
total += n;
std::cout << "[" << getCurrentTime() << "] Connection " << _fd
<< " read " << n << " bytes (total: " << total << ")" << std::endl;
// 边缘触发模式下,数据小于缓冲区大小时退出循环
if (_triggerMode == TriggerMode::EDGE_TRIGGER && n < sizeof(buffer))
{
break;
}
}
else if (n == 0)
{
std::cout << "[" << getCurrentTime() << "] Connection " << _fd << " closed by client" << std::endl;
return 0;
}
else
{
// 非阻塞模式下无数据可读,正常退出
if (errno == EAGAIN || errno == EWOULDBLOCK)
{
break;
}
//其他情况说明发生错误了
else
{
std::cerr << "[" << getCurrentTime() << "] Connection " << _fd
<< " read error: " << strerror(errno) << std::endl;
return -1;
}
}
}
return total;
}
// 从缓冲区发送数据
ssize_t sendData()
{
if (_sendBuffer.empty())
{
return 0;
}
//因为send函数是把用户空间数据拷贝到内核态缓冲区(skb缓冲区队列),一般情况下都是可以一次性拷贝的。所以不需要循环写
//一旦内核的缓冲区队列满了,则返回值n<0
ssize_t n = send(_fd, _sendBuffer.data(), _sendBuffer.size(), 0);
if (n > 0)
{
std::cout << "[" << getCurrentTime() << "] Connection " << _fd
<< " sent " << n << " bytes" << std::endl;
_sendBuffer.erase(_sendBuffer.begin(), _sendBuffer.begin() + n);
}
else if (n == 0)
{
std::cout << "[" << getCurrentTime() << "] Connection " << _fd << " send 0 bytes" << std::endl;
return 0;
}
//返回值小于0说明缓冲区无空间,此时需要判断是真的没空间还是发生错误了。
else
{
if (errno == EAGAIN || errno == EWOULDBLOCK)
{
std::cout << "[" << getCurrentTime() << "] Connection " << _fd
<< " send buffer full, will retry" << std::endl;
return 0;
}
else
{
std::cerr << "[" << getCurrentTime() << "] Connection " << _fd
<< " send error: " << strerror(errno) << std::endl;
return -1;
}
}
return n;
}
// 常用访问函数
int getFd() const { return _fd; }
std::vector<char>& getRecvBuffer() { return _recvBuffer; }
std::vector<char>& getSendBuffer() { return _sendBuffer; }
TriggerMode getTriggerMode() const { return _triggerMode; }
// 构造函数
explicit Connection(int fd, TriggerMode mode = TriggerMode::LEVEL_TRIGGER)
: _fd(fd), _triggerMode(mode)
{
_recvBuffer.reserve(4096);
_sendBuffer.reserve(4096);
// 设置非阻塞模式
int flags = fcntl(_fd, F_GETFL, 0);
if (flags == -1)
{
std::cerr << "[" << getCurrentTime() << "] fcntl GETFL error: " << strerror(errno) << std::endl;
}
else if (fcntl(_fd, F_SETFL, flags | O_NONBLOCK) == -1)
{
std::cerr << "[" << getCurrentTime() << "] fcntl SETFL error: " << strerror(errno) << std::endl;
}
std::cout << "[" << getCurrentTime() << "] Connection " << _fd << " created (mode: "
<< (mode == TriggerMode::LEVEL_TRIGGER ? "LT" : "ET") << ")" << std::endl;
}
// 析构函数
~Connection()
{
if (_fd != -1)
{
std::cout << "[" << getCurrentTime() << "] Connection " << _fd << " closed" << std::endl;
close(_fd);
_fd = -1;
}
}
// 禁用拷贝
Connection(const Connection&) = delete;
Connection& operator=(const Connection&) = delete;
// 移动构造
Connection(Connection&& other) noexcept
: _fd(other._fd)
, _recvBuffer(std::move(other._recvBuffer))
, _sendBuffer(std::move(other._sendBuffer))
, _triggerMode(other._triggerMode)
{
other._fd = -1;
}
};
// 2. 事件处理器接口
class EventHandler
{
protected:
std::unique_ptr<Connection> _connection;
public:
int getFd() const { return _connection->getFd(); }
//这里因为使用了智能指针unique_ptr所以要用get函数获取原生指针
Connection* getConnection() { return _connection.get(); }
// 事件处理接口
virtual void handleRead() = 0;
virtual void handleWrite() = 0;
virtual void handleError() = 0;
// 构造函数
explicit EventHandler(std::unique_ptr<Connection> conn)
: _connection(std::move(conn))
{
std::cout << "[" << getCurrentTime() << "] EventHandler created for fd: " << getFd() << std::endl;
}
// 析构函数
virtual ~EventHandler()
{
std::cout << "[" << getCurrentTime() << "] EventHandler destroyed for fd: " << getFd() << std::endl;
}
// 禁用拷贝
EventHandler(const EventHandler&) = delete;
EventHandler& operator=(const EventHandler&) = delete;
};
// 3. 事件多路分发器接口
class EventDemultiplexer
{
public:
virtual int waitEvents(int timeout, std::vector<std::pair<int, EventType>>& activeEvents) = 0;
virtual void registerEvent(int fd, EventType type) = 0;
virtual void registerEvent(int fd, EventType type, TriggerMode mode) = 0;
virtual void removeEvent(int fd, EventType type) = 0;
virtual ~EventDemultiplexer() = default;
};
// 4. epoll事件多路分发器
class EpollDemultiplexer : public EventDemultiplexer
{
private:
int _epollfd;
static const int MAX_EVENTS = 1024;
epoll_event _events[MAX_EVENTS];
public:
// 等待事件就绪
int waitEvents(int timeout, std::vector<std::pair<int, EventType>>& activeEvents) override
{
activeEvents.clear();
int nfds = epoll_wait(_epollfd, _events, MAX_EVENTS, timeout);
if (nfds == -1)
{
if (errno == EINTR)
{
// 被信号中断,返回0表示无事件
return 0;
}
std::cerr << "[" << getCurrentTime() << "] epoll_wait error: " << strerror(errno) << std::endl;
return -1;
}
// 解析事件
for (int i = 0; i < nfds; i++)
{
int fd = _events[i].data.fd;
uint32_t epoll_event = _events[i].events;
if (epoll_event & EPOLLIN)
{
activeEvents.emplace_back(fd, EventType::EVENT_READ);
}
if (epoll_event & EPOLLOUT)
{
activeEvents.emplace_back(fd, EventType::EVENT_WRITE);
}
if (epoll_event & EPOLLERR)
{
activeEvents.emplace_back(fd, EventType::EVENT_ERROR);
}
}
std::cout << "[" << getCurrentTime() << "] epoll_wait returned " << nfds << " events" << std::endl;
return nfds;
}
// 注册事件(默认水平触发)
void registerEvent(int fd, EventType type) override
{
registerEvent(fd, type, TriggerMode::LEVEL_TRIGGER);
}
// 注册事件(带触发模式)
void registerEvent(int fd, EventType type, TriggerMode mode) override
{
epoll_event event{};
event.data.fd = fd;
event.events = static_cast<uint32_t>(type);
if (mode == TriggerMode::EDGE_TRIGGER)
{
event.events |= EPOLLET;
}
// 先尝试修改事件,失败则添加
if (epoll_ctl(_epollfd, EPOLL_CTL_MOD, fd, &event) == -1)
{
if (errno == ENOENT)
{
// 事件不存在,添加新事件
if (epoll_ctl(_epollfd, EPOLL_CTL_ADD, fd, &event) == -1)
{
std::cerr << "[" << getCurrentTime() << "] epoll_ctl ADD error (fd=" << fd
<< "): " << strerror(errno) << std::endl;
return;
}
std::cout << "[" << getCurrentTime() << "] epoll added event for fd: " << fd << std::endl;
}
else
{
std::cerr << "[" << getCurrentTime() << "] epoll_ctl MOD error (fd=" << fd
<< "): " << strerror(errno) << std::endl;
return;
}
}
else
{
std::cout << "[" << getCurrentTime() << "] epoll modified event for fd: " << fd << std::endl;
}
}
// 移除事件
void removeEvent(int fd, EventType type) override
{
epoll_event event{};
event.data.fd = fd;
event.events = static_cast<uint32_t>(type);
if (epoll_ctl(_epollfd, EPOLL_CTL_DEL, fd, &event) == -1)
{
if (errno != ENOENT)
{
std::cerr << "[" << getCurrentTime() << "] epoll_ctl DEL error (fd=" << fd
<< "): " << strerror(errno) << std::endl;
}
else
{
std::cout << "[" << getCurrentTime() << "] epoll event for fd " << fd << " not found, ignoring" << std::endl;
}
}
else
{
std::cout << "[" << getCurrentTime() << "] epoll removed event for fd: " << fd << std::endl;
}
}
// 构造函数
EpollDemultiplexer()
{
// 使用epoll_create1更安全,设置EPOLL_CLOEXEC标志
_epollfd = epoll_create1(EPOLL_CLOEXEC);
if (_epollfd == -1)
{
std::cerr << "[" << getCurrentTime() << "] epoll_create1 error: " << strerror(errno) << std::endl;
exit(EXIT_FAILURE);
}
std::cout << "[" << getCurrentTime() << "] EpollDemultiplexer created (epollfd=" << _epollfd << ")" << std::endl;
}
// 析构函数
~EpollDemultiplexer() override
{
if (_epollfd != -1)
{
std::cout << "[" << getCurrentTime() << "] Closing epollfd: " << _epollfd << std::endl;
close(_epollfd);
_epollfd = -1;
}
}
};
// 5. Reactor核心
class Reactor
{
private:
std::unique_ptr<EventDemultiplexer> _demultiplexer;
std::map<int, std::unique_ptr<EventHandler>> _handlers;
bool _isrunning;
public:
// 构造函数
explicit Reactor(std::unique_ptr<EventDemultiplexer> demux)
: _demultiplexer(std::move(demux)), _isrunning(false)
{
std::cout << "[" << getCurrentTime() << "] Reactor created" << std::endl;
}
// 注册新的事件处理器
void registerHandler(std::unique_ptr<EventHandler> handler, EventType type)
{
int fd = handler->getFd();
std::cout << "[" << getCurrentTime() << "] Registering handler for fd: " << fd << std::endl;
// 存储处理器到内核中
_handlers[fd] = std::move(handler);
// 注册事件到分发器中
auto conn = _handlers[fd]->getConnection();
auto epollDemux = dynamic_cast<EpollDemultiplexer*>(_demultiplexer.get());
if (epollDemux)
{
epollDemux->registerEvent(fd, type, conn->getTriggerMode());
}
else
{
_demultiplexer->registerEvent(fd, type);
}
}
/*
*/
// 更新事件类型(关键修复:不转移所有权,只更新事件)
void updateHandler(int fd, EventType type)
{
auto it = _handlers.find(fd);
if (it == _handlers.end())
{
std::cerr << "[" << getCurrentTime() << "] Update handler failed: fd " << fd << " not found" << std::endl;
return;
}
std::cout << "[" << getCurrentTime() << "] Updating handler for fd " << fd << " to event type: "
<< (type == EventType::EVENT_READ ? "READ" : "WRITE") << std::endl;
auto conn = it->second->getConnection();
auto epollDemux = dynamic_cast<EpollDemultiplexer*>(_demultiplexer.get());
if (epollDemux)
{
epollDemux->registerEvent(fd, type, conn->getTriggerMode());
}
else
{
_demultiplexer->registerEvent(fd, type);
}
}
// 移除事件处理器
void removeHandler(int fd)
{
if (_handlers.count(fd))
{
std::cout << "[" << getCurrentTime() << "] Removing handler for fd: " << fd << std::endl;
// 从分发器中移除所有事件
_demultiplexer->removeEvent(fd, EventType::EVENT_READ);
_demultiplexer->removeEvent(fd, EventType::EVENT_WRITE);
_demultiplexer->removeEvent(fd, EventType::EVENT_ERROR);
// 从核心中移除处理器
_handlers.erase(fd);
}
else
{
std::cout << "[" << getCurrentTime() << "] Remove handler failed: fd " << fd << " not found" << std::endl;
}
}
// 获取事件处理器
EventHandler* getHandler(int fd)
{
auto it = _handlers.find(fd);
return (it != _handlers.end()) ? it->second.get() : nullptr;
}
// 启动事件循环
void start()
{
if (_isrunning)
{
std::cout << "[" << getCurrentTime() << "] Reactor already running" << std::endl;
return;
}
_isrunning = true;
std::cout << "[" << getCurrentTime() << "] Reactor starting event loop" << std::endl;
eventloop();
}
// 停止事件循环
void stop()
{
_isrunning = false;
std::cout << "[" << getCurrentTime() << "] Reactor stopping event loop" << std::endl;
}
private:
// 事件循环
void eventloop()
{
while (_isrunning)
{
std::vector<std::pair<int, EventType>> activeEvents;
int n = _demultiplexer->waitEvents(1000, activeEvents);
if (n < 0)
{
std::cerr << "[" << getCurrentTime() << "] Event loop error, stopping" << std::endl;
break;
}
// 处理就绪事件
for (const auto& [fd, type] : activeEvents)
{
EventHandler* handler = getHandler(fd);
if (!handler)
{
std::cerr << "[" << getCurrentTime() << "] No handler found for fd: " << fd << std::endl;
continue;
}
try
{
switch (type)
{
case EventType::EVENT_READ:
std::cout << "[" << getCurrentTime() << "] Handling READ event for fd: " << fd << std::endl;
handler->handleRead();
break;
case EventType::EVENT_WRITE:
std::cout << "[" << getCurrentTime() << "] Handling WRITE event for fd: " << fd << std::endl;
handler->handleWrite();
break;
case EventType::EVENT_ERROR:
std::cout << "[" << getCurrentTime() << "] Handling ERROR event for fd: " << fd << std::endl;
handler->handleError();
removeHandler(fd);
break;
}
}
catch (const std::exception& e)
{
std::cerr << "[" << getCurrentTime() << "] Error handling event for fd " << fd
<< ": " << e.what() << std::endl;
removeHandler(fd);
}
}
}
}
};
// 6. 具体事件处理器实现
// 连接处理器(处理已建立连接的读写)
class ConnectionHandler : public EventHandler {
private:
Reactor* _reactor;
public:
ConnectionHandler(std::unique_ptr<Connection> conn, Reactor* reactor)
: EventHandler(std::move(conn)), _reactor(reactor) {}
void handleRead() override {
auto conn = getConnection();
ssize_t n = conn->readData();
if (n <= 0) {
// 连接关闭或错误,移除处理器
_reactor->removeHandler(getFd());
return;
}
// 简单回声逻辑:将接收的数据放入发送缓冲区
auto& recvBuf = conn->getRecvBuffer();
auto& sendBuf = conn->getSendBuffer();
sendBuf.insert(sendBuf.end(), recvBuf.begin(), recvBuf.end());
std::cout << "[" << getCurrentTime() << "] Connection " << getFd()
<< " echoing " << recvBuf.size() << " bytes" << std::endl;
recvBuf.clear();
/*
这里非常关键,在之前我们的代码逻辑是注册写事件,调用的是registerHandler函数,而这个函数使用的是移动赋值。_handler[fd]=std::move(handler)
即将现在的处理器类移动给了Reactor核心,但是我们reactor在获得新连接,创建Connection的时候已经创建了处理器类,核心中的unique_ptr已经有指向
此时调用rigisterHandler又创建了一个unique_ptr,然后将第二个指针移动赋值给了核心。
问题出现了:核心中的unique_ptr和这里临时创建的unique_ptr都指向同一个处理器类。当智能指针声明周期结束的时候,两次析构,程序崩溃。
*/
//我们由此也明白一个关键道理:
//处理读事件后,修改监控事件为写事件;处理写事件后,修改监控事件为读事件。而不是重新注册事件
//体现一个轮转性
// 关键修复:使用updateHandler更新事件类型,不转移所有权
_reactor->updateHandler(getFd(), EventType::EVENT_WRITE);
}
void handleWrite() override {
auto conn = getConnection();
ssize_t n = conn->sendData();
if (n < 0) {
// 发送错误,移除处理器
_reactor->removeHandler(getFd());
return;
}
// 发送完成后,重新注册读事件(保持连接)
if (conn->getSendBuffer().empty()) {
std::cout << "[" << getCurrentTime() << "] Connection " << getFd()
<< " send complete, waiting for new data" << std::endl;
_reactor->updateHandler(getFd(), EventType::EVENT_READ);
}
// 未发送完成会继续触发写事件(epoll默认行为)
}
void handleError() override {
std::cerr << "[" << getCurrentTime() << "] Connection " << getFd() << " error occurred" << std::endl;
}
};
// 监听处理器(处理新连接)
class AcceptorHandler : public EventHandler {
private:
Reactor* _reactor;
TriggerMode _triggerMode;
public:
AcceptorHandler(std::unique_ptr<Connection> conn, Reactor* reactor, TriggerMode mode)
: EventHandler(std::move(conn)), _reactor(reactor), _triggerMode(mode) {}
void handleRead() override {
struct sockaddr_in clientAddr;
socklen_t clientLen = sizeof(clientAddr);
int clientFd = accept(getFd(), (struct sockaddr*)&clientAddr, &clientLen);
if (clientFd == -1) {
std::cerr << "[" << getCurrentTime() << "] Accept error: " << strerror(errno) << std::endl;
return;
}
// 打印新连接信息
std::cout << "[" << getCurrentTime() << "] New connection from "
<< inet_ntoa(clientAddr.sin_addr) << ":" << ntohs(clientAddr.sin_port)
<< " (fd=" << clientFd << ")" << std::endl;
// 创建新连接处理器并注册
auto conn = std::make_unique<Connection>(clientFd, _triggerMode);
auto handler = std::make_unique<ConnectionHandler>(std::move(conn), _reactor);
_reactor->registerHandler(std::move(handler), EventType::EVENT_READ);
}
void handleWrite() override {
// 监听套接字通常不处理写事件
std::cout << "[" << getCurrentTime() << "] Unexpected WRITE event on listener fd: " << getFd() << std::endl;
}
void handleError() override {
std::cerr << "[" << getCurrentTime() << "] Listener fd " << getFd() << " error occurred" << std::endl;
}
};
// 主函数
int main() {
// 创建监听套接字
int listenFd = socket(AF_INET, SOCK_STREAM, 0);
if (listenFd == -1) {
std::cerr << "[" << getCurrentTime() << "] socket creation failed: " << strerror(errno) << std::endl;
return 1;
}
// 设置端口复用
int opt = 1;
if (setsockopt(listenFd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1) {
std::cerr << "[" << getCurrentTime() << "] setsockopt failed: " << strerror(errno) << std::endl;
close(listenFd);
return 1;
}
// 绑定地址
struct sockaddr_in serverAddr;
memset(&serverAddr, 0, sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
serverAddr.sin_addr.s_addr = INADDR_ANY;
serverAddr.sin_port = htons(8080);
if (bind(listenFd, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) == -1) {
std::cerr << "[" << getCurrentTime() << "] bind failed: " << strerror(errno) << std::endl;
close(listenFd);
return 1;
}
// 开始监听
if (listen(listenFd, SOMAXCONN) == -1) {
std::cerr << "[" << getCurrentTime() << "] listen failed: " << strerror(errno) << std::endl;
close(listenFd);
return 1;
}
std::cout << "[" << getCurrentTime() << "] Server listening on port 8080 (fd=" << listenFd << ")" << std::endl;
// 初始化Reactor
auto demultiplexer = std::make_unique<EpollDemultiplexer>();
Reactor reactor(std::move(demultiplexer));
// 创建并注册Acceptor(使用水平触发模式)
auto conn = std::make_unique<Connection>(listenFd, TriggerMode::LEVEL_TRIGGER);
auto acceptor = std::make_unique<AcceptorHandler>(std::move(conn), &reactor, TriggerMode::LEVEL_TRIGGER);
reactor.registerHandler(std::move(acceptor), EventType::EVENT_READ);
// 启动事件循环
reactor.start();
return 0;
}
五、总结
Reactor设计模式是一种常见的设计模式,他把各个模块解耦,提高了代码的稳定性和可扩展性。而网络epoll则天然适配Reactor模式,因为Reactor模式是一种事件驱动的设计模式,通过事件循环机制高效处理并发事件。这与网络epoll模型不谋而合。
其核心包含事件源、多路分发器、事件处理器和Reactor协调器四个组件,工作流程包括事件注册、监控、分发和处理。该模式采用接口化设计,定义事件类型、处理器接口、分发器接口等抽象层,实现稳定点与变化点的解耦。在网络编程中,Reactor模式与epoll机制天然适配,通过封装连接类管理文件描述符和缓冲区,有效提升代码的可维护性和扩展性。该模式将直观的FD类型判断转化为抽象的事件驱动处理,显著降低了复杂系统的代码臃肿度。