反應器的基本原理是:
?針對關心的某個事件寫一個事件處理器(event_handler). 將該事件處理器登記到反應器中(同時指明關心的事件).?
?然后反應器會自動檢測事件的發生. 并調用預先登記的事件處理器中的回調函數.?
所以ACE Reactor 框架的責任:
1、檢測來自各種事件源的事件的發生。
2、將事件多路分離給其預先登記的事件處理器。
3、分派給處理器所定義的掛鉤方法,從而以一種應用定義的方式處理這些事件。
6.2 事件處理器
在ACE中.?反應器是ACE_Reactor類的單件對象(因為程序中通常只需要一個反應器).?
反應器提供了登記/撤銷 事件處理器的接口.?register_handler() /?remove_handler() .
這些接口要求 事件處理器必須是?ACE_Event_Handler?類型的. 所以我們的事件處理器類必須從該類繼承.
在反應器需要檢測某個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 ? 建立連接時 ? 回調 handle_input()
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:處理正常, -1: 連接被關閉, -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{
...
};