反应器组件 ACE_Reactor

6.1 反应器组件 ACE_Reactor

反应器的基本原理是:
针对关心的某个事件写一个事件处理器(event_handler). 将该事件处理器登记到反应器中(同时指明关心的事件).
然后反应器会自动检测事件的发生. 并调用预先登记的事件处理器中的回调函数.

所以ACE Reactor 框架的责任:

1、检测来自各种事件源的事件的发生。

2、将事件多路分离给其预先登记的事件处理器。

3、分派给处理器所定义的挂钩方法,从而以一种应用定义的方式处理这些事件。


6.2 事件处理器

在ACE中.反应器是ACE_Reactor类的单件对象(因为程序中通常只需要一个反应器).
反应器提供了登记/撤销 事件处理器的接口.register_handler() /remove_handler() .
这些接口要求 事件处理器必须是ACE_Event_Handler类型的. 所以我们的事件处理器类必须从该类继承.

在ACE_Event_Handler类中定义了一些类似"handle_***" 的回调方法. 我们必须在派生类中重写我们敢兴趣的.
在反应器需要检测某个I/O句柄上是否有事件时. 需要知道原始句柄. 这样就需要重写事件处理器类的get_handle()函数.
下边是ACE_Event_Handler 中声明的钩子函数:
handle_signal ()当在反应器上登记的信号发生时. 反应器回调该函数. (不懂)
handle_input ()当来自I/O设备的输入可用时. 反应器自动回调该方法.
handle_exception () 当在反应器上登记的异常事件发生时. (不懂)
handle_timeout ()当在反应器上登记的定时器超时的时候. 回调该方法.
handle_output ()当在IO设备上的输出可用时. 回调该方法.
6.2.1 登记事件处理器
使用 ACE_Reactor 类的register_handler()函数. 这个函数有好几个重载形式.
该函数有个参数用来指出感兴趣的事件. 它可以是下边一些常量 (定义在ACE_Event_handler类中):
READ_MASK 句柄上有数据可读时 回调 handle_input()
WRITE_MASK 句柄上可写时 回调 handle_output()
TIMER_MASK 回调 handle_close() 不懂怎么用...
ACCEPT_MASK 有来自客户端的新的连接请求时 回调 handle_input()
CONNECT_MASK 建立连接时 DONT_CALL 它用在显式拆除事件处理器的remove_handler()函数中. 表示拆除前不调用 handler_close() 函数.

6.2.2 拆除事件处理器
当不在需要处理某个事件时. 需要把对应的事件处理器从反应器中拆除.
两种拆除事件处理器的办法:
一种是隐式的自动拆除.当事件处理器类中的 handle_*** 方法返回的int 小于0 时. 反应器会自动调用事件处理器
的Handle_close()方法. 并把事件处理器拆除.
另一种是显式拆除. 即调用 ACE_reactor::remove_handler(). 这也会调用事件处理器的handle_close(). 然后拆除.
不过. 如果你不需要调用handle_close(). 可以给remove_handler()传递参数 ACE_Event_Handler::DONT_CALL .
具体例子在后边会给出.


我在这里创建了一个简单的Event_handler:

class Event_Handler
{
public:
Event_Handler();
virtual ~Event_Handler();
public:
//! 获取反应器
//! @return 反应器指针
Reactor* reactor();
//! 设置反应器
//! @param reactor 反应器指针
void reactor(Reactor* reactor);
//! 获取通道id
//! @return 通道id
virtual uint32_t get_id() = 0;
//! 获取socket句柄
//! @return socket句柄
virtual SOCKET get_handle() = 0;
//! 处理读
//! @return 处理结果 0:处理正常,-1: 连接被关闭,-2:连接异常
virtual int handle_input() = 0;
//! 处理写
//! @return 处理结果 0:处理正常,-2:连接异常
virtual int handle_output() = 0;
//! 连接异常
virtual int handle_exception() = 0;
//! 连接关闭
virtual int handle_close() = 0;
//! 超时
virtual int handle_timeout() = 0;
//! 提交发送任务
//! @param send_task 待发送的任务
virtual int post_packet(Net_Packet *send_packet) = 0;
public:
list_head hashitem;
bool read;
bool write;
bool notify_close;
time_t timeout; //<! 超时的时间,0表示没有设置超时
private:
//! 反应器
Reactor *m_reactor;
};

然后创建对应的处理类:

//! @class SOCK_Acceptor
//! @brief tcp监听处理类
class SOCK_Acceptor : public Event_Handler{

...

};

//! @class SOCK_Connector
//! @brief tcp连接处理类
class SOCK_Connector : public Event_Handler{

//! @class SOCK_Stream
//! @brief tcp通道处理类
class SOCK_Stream : public Event_Handl{

};

相关文章

react 中的高阶组件主要是对于 hooks 之前的类组件来说的,如...
我们上一节了解了组件的更新机制,但是只是停留在表层上,例...
我们上一节了解了 react 的虚拟 dom 的格式,如何把虚拟 dom...
react 本身提供了克隆组件的方法,但是平时开发中可能很少使...
mobx 是一个简单可扩展的状态管理库,中文官网链接。小编在接...
我们在平常的开发中不可避免的会有很多列表渲染逻辑,在 pc ...