ACE反應器 Reactor 模式 2

2021-04-25 01:47:01 字數 2558 閱讀 7656

在socket程式設計中,常見的事件就是"讀就緒","寫就緒",通過對這兩個事件的捕獲分發,可以實現socket中的非同步操作。

socket程式設計中的事件處理器

在前面我們已經介紹過,在ace反應器框架中,任何都必須派生自ace_event_handler類,並通過過載其相應會調事件處理函式來實現相應的**處理的。在socket程式設計中,我們通常需要過載的函式有

handle_input()

當i/o控制代碼(比如unix中的檔案描述符)上的輸入可用時,反應器自動**該方法。

handle_output()

當i/o裝置的輸出佇列有可用空間時,反應器自動**該方法。

handle_close()

當事件處理器中的事件從reactor中移除的時候呼叫。

此外,為了使reactor能通過i/o控制代碼找到對應的事件處理器,還必須過載其get_handle()方法以使得reactor建立起i/o控制代碼和事件處理器的關聯。

使用reactor框架。

下面我們將以乙個客戶端的程式為例,介紹如何在socket程式設計中使用reactor框架。

一.建立乙個客戶端物件(事件處理器)。

客戶端物件就是乙個事件處理器,其宣告如下:

class client:public ace_event_handler;

在client端中我只關心"讀就緒"事件,故只過載了handle_input函式(大多數應用下只需要過載handle_input函式)。另外,在客戶端還儲存了乙個ace_sock_stream的peer物件用來進行socket通訊,同時封裝了乙個peer()函式返回它的引用。

二.過載相應**處理函式

ace_sock_stream& client::peer()

ace_handle client::get_handle(void) const

int client::handle_input (ace_handle fd)

else

//socket連線發生錯誤,返回-1,在reactor中登出事件,觸發handle_close函式

}int client::handle_close (ace_handle handle,

ace_reactor_mask close_mask)

幾個函式的功能都非常簡單,這裡就不多做介紹了。

三.在reactor中註冊事件

首先讓我們來看看相應的main函式的**:

int main(int argc, char *argv)

ace_reactor::instance()->register_handler(&client,ace_event_handler::read_mask);

while(true)

return 0; }

在這裡可以看到,使用reactor框架後,依然首先通過ace_sock_connector的connect函式來建立連線。建立連線後,可以通過ace_reactor::instance()->register_handler函式來實現reactor的註冊,實現i/o事件和client物件的handle_input方法相關聯,它的第乙個引數是事件處理器的位址,第二個引數是事件型別,由於這裡只關心讀就緒事件,故註冊的事件型別是ace_event_handler::read_mask。

四.啟動reactor事件迴圈

通過如上設定後,我們就可以通過ace_reactor::instance()->handle_events()啟動reactor迴圈了,這樣,每當伺服器端有資料傳送給客戶端時,當客戶端的資料就緒時,就回觸發client物件的handle_input函式,將接收的資料列印出來。

通常的做法是,將reactor事件迴圈作為乙個單獨的執行緒來處理,這樣就不會阻塞main函式。

五.登出reactor事件

reactor事件的登出一般有兩種方式,顯式和隱式,下面將分別給予介紹。

隱式登出。

當reactor捕獲事件後,會觸發相應的"handle_"處理函式,當"handle_"處理函式返回值大於或等於0時,表示處理事件成功,當返回值小於0時,表示處理事件失敗,這時reactor會自動登出該控制代碼所註冊的所有事件,並觸發handle_close函式,以執行相應的資源清理工作。

在本例中,當handle_input函式裡的recv函式接收到0個數時,說明socket發生錯誤(大多為socket連線中斷),此時返回-1,則系統自動登出相應事件。

顯示登出。

呼叫reactor物件的remove_handler方法移除,它有兩個引數,第乙個是所註冊的事件反應器物件,第二個是所要登出的事件。

在這個示例程式裡,連線方只有乙個socket連線,reactor的優勢並沒有體現出來,但在一些網路管理系統裡,連線方需要對多個需要管理的裝置(伺服器端)進行連線,在這種情況下使用reactor模式,只需要多開乙個reactor事件迴圈執行緒就能實現事件多路分發復用,並且不會阻塞,通過物件導向的**方式管理,使用起來非常方便。

reactor框架的另外乙個常用的地方就是伺服器端,一般是乙個伺服器端對應多個客戶端,這樣用reactor模式能大幅提高併發能力,這方面的程式設計方法將在下一章給與介紹。

ACE反應器 Reactor 模式 3

在伺服器端使用reactor框架 使用reactor框架的伺服器端結構如下 伺服器端註冊兩種事件處理器,clientacceptor和clientservice clientservice類負責和客戶端的通訊,每乙個clientservice物件對應乙個客戶端的socket連線。clientacce...

ACE反應器 Reactor 模式 4

定時器的實現 通過reactor機制,還可以很容易的實現定時器的功能,使用方式如下。編寫乙個事件反應器,過載 handle timeout 方法,該方法是定時器的觸發時間到時,會自動觸發該方法。通過reactor的 schedule timer 方法註冊定時器。啟動reacotr的 handle e...

ACE反應器 Reactor 模式 4

定時器的實現 通過reactor機制,還可以很容易的實現定時器的功能,使用方式如下。編寫乙個事件反應器,過載 handle timeout 方法,該方法是定時器的觸發時間到時,會自動觸發該方法。通過reactor的 schedule timer 方法註冊定時器。啟動reacotr的 handle e...