日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

ACE反应器(Reactor)模式

發(fā)布時(shí)間:2025/3/21 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ACE反应器(Reactor)模式 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

1ACE反應(yīng)器框架簡(jiǎn)介

反應(yīng)器(Reactor):用于事件多路分離和分派的體系結(jié)構(gòu)模式

通常的,對(duì)一個(gè)文件描述符指定的文件或設(shè)備, 有兩種工作方式:?阻塞非阻塞。所謂阻塞方式的意思是指, 當(dāng)試圖對(duì)該文件描述符進(jìn)行讀寫(xiě)時(shí),如果當(dāng)時(shí)沒(méi)有東西可讀,或者暫時(shí)不可寫(xiě), 程序就進(jìn)入等待狀態(tài), 直到有東西可讀或者可寫(xiě)為止。而對(duì)于非阻塞狀態(tài),如果沒(méi)有東西可讀, 或者不可寫(xiě), 讀寫(xiě)函數(shù)馬上返回,而不會(huì)等待

在前面的章節(jié)中提到的Tcp通信的例子中,就是采用的阻塞式的工作方式:當(dāng)接收tcp數(shù)據(jù)時(shí),如果遠(yuǎn)端沒(méi)有數(shù)據(jù)可以讀,則會(huì)一直阻塞到讀到需要的數(shù)據(jù)為止。這種方式的傳輸和傳統(tǒng)的被動(dòng)方法的調(diào)用類似,非常直觀,并且簡(jiǎn)單有效,但是同樣也存在一個(gè)效率問(wèn)題,如果你是開(kāi)發(fā)一個(gè)面對(duì)著數(shù)千個(gè)連接的服務(wù)器程序,對(duì)每一個(gè)客戶端都采用阻塞的方式通信,如果存在某個(gè)非常耗時(shí)的讀寫(xiě)操作時(shí),其它的客戶端通信將無(wú)法響應(yīng),效率非常低下。

一種常用做法是:每建立一個(gè)Socket連接時(shí),同時(shí)創(chuàng)建一個(gè)新線程對(duì)該Socket進(jìn)行單獨(dú)通信(采用阻塞的方式通信)。這種方式具有很高的響應(yīng)速度,并且控制起來(lái)也很簡(jiǎn)單,在連接數(shù)較少的時(shí)候非常有效,但是如果對(duì)每一個(gè)連接都產(chǎn)生一個(gè)線程的無(wú)疑是對(duì)系統(tǒng)資源的一種浪費(fèi),如果連接數(shù)較多將會(huì)出現(xiàn)資源不足的情況。

另一種較高效的做法是:服務(wù)器端保存一個(gè)Socket連接列表,然后對(duì)這個(gè)列表進(jìn)行輪詢,如果發(fā)現(xiàn)某個(gè)Socket端口上有數(shù)據(jù)可讀時(shí)(讀就緒),則調(diào)用該socket連接的相應(yīng)讀操作;如果發(fā)現(xiàn)某個(gè)Socket端口上有數(shù)據(jù)可寫(xiě)時(shí)(寫(xiě)就緒),則調(diào)用該socket連接的相應(yīng)寫(xiě)操作;如果某個(gè)端口的Socket連接已經(jīng)中斷,則調(diào)用相應(yīng)的析構(gòu)方法關(guān)閉該端口。這樣能充分利用服務(wù)器資源,效率得到了很大提高。

在Socket編程中就可以通過(guò)select等相關(guān)API實(shí)現(xiàn)這一方式。但直接用這些API控制起來(lái)比較麻煩,并且也難以控制和移植,在ACE中可以通過(guò)Reactor模式簡(jiǎn)化這一開(kāi)發(fā)過(guò)程。

反應(yīng)器本質(zhì)上提供一組更高級(jí)的編程抽象,簡(jiǎn)化了事件驅(qū)動(dòng)的分布式應(yīng)用的設(shè)計(jì)和實(shí)現(xiàn)。除此而外,反應(yīng)器還將若干不同種類的事件的多路分離集成到易于使用的API中。特別地,反應(yīng)器對(duì)基于定時(shí)器的事件、信號(hào)事件、基于I/O端口監(jiān)控的事件和用戶定義的通知進(jìn)行統(tǒng)一地處理。

ACE中的反應(yīng)器與若干內(nèi)部和外部組件協(xié)同工作。其基本概念是反應(yīng)器框架檢測(cè)事件的發(fā)生(通過(guò)在OS事件多路分離接口上進(jìn)行偵聽(tīng)),并發(fā)出對(duì)預(yù)登記事件處理器(eventhandler)對(duì)象中的方法的"回調(diào)"(callback)。該方法由應(yīng)用開(kāi)發(fā)者實(shí)現(xiàn),其中含有應(yīng)用處理此事件的特定代碼。

使用ACE的反應(yīng)器,只需如下幾步:

  • 創(chuàng)建事件處理器,以處理他所感興趣的某事件。
  • 在反應(yīng)器上登記,通知說(shuō)他有興趣處理某事件,同時(shí)傳遞他想要用以處理此事件的事件處理器的指針給反應(yīng)器。
  • 隨后反應(yīng)器框架將自動(dòng)地:

  • 在內(nèi)部維護(hù)一些表,將不同的事件類型與事件處理器對(duì)象關(guān)聯(lián)起來(lái)。
  • 在用戶已登記的某個(gè)事件發(fā)生時(shí),反應(yīng)器發(fā)出對(duì)處理器中相應(yīng)方法的回調(diào)。
  • 反應(yīng)器模式在ACE中被實(shí)現(xiàn)為ACE_Reactor類,它提供反應(yīng)器框架的功能接口。

    如上面所提到的,反應(yīng)器將事件處理器對(duì)象作為服務(wù)提供者使用。反應(yīng)器內(nèi)部記錄某個(gè)事件處理器特定事件的相關(guān)回調(diào)方法。當(dāng)這些事件發(fā)生時(shí),反應(yīng)器會(huì)創(chuàng)建這種事件和相應(yīng)的事件處理器的關(guān)聯(lián)。

  • 事件處理器
    事件處理器就是需要通過(guò)輪詢發(fā)生事件改變的對(duì)象列表中的對(duì)象,如在上面的例子中就是連接的客戶端,每個(gè)客戶端都可以看成一個(gè)事件處理器。
  • 回調(diào)事件
    就是反應(yīng)器支持的事件,如Socket讀就緒,寫(xiě)就緒。拿上面的例子來(lái)說(shuō),如果某個(gè)客戶端(事件處理器)在反應(yīng)器中注冊(cè)了讀就緒事件,當(dāng)客戶端給服務(wù)器發(fā)送一條消息的時(shí)候,就會(huì)觸發(fā)這個(gè)客戶端的數(shù)據(jù)可讀的回調(diào)函數(shù)。
  • 在反應(yīng)器框架中,所有應(yīng)用特有的事件處理器都必須由ACE_Event_Handler的抽象接口類派生。可以通過(guò)重載相應(yīng)的"handle_"方法實(shí)現(xiàn)相關(guān)的回調(diào)方法。

    使用ACE_Reactor基本上有三個(gè)步驟:

  • 創(chuàng)建ACE_Event_Handler的子類,并在其中實(shí)現(xiàn)適當(dāng)?shù)?#34;handle_"方法,以處理你想要此事件處理器為之服務(wù)的事件類型。
  • 通過(guò)調(diào)用反應(yīng)器對(duì)象的register_handler(),將你的事件處理器登記到反應(yīng)器。
  • 在事件發(fā)生時(shí),反應(yīng)器將自動(dòng)回調(diào)相應(yīng)的事件處理器對(duì)象的適當(dāng)?shù)膆andle_"方法
  • 下面我就以一個(gè)Socket客戶端的例子為例簡(jiǎn)單的說(shuō)明反應(yīng)器的基本用法。

    ?

    Cpp代碼??
  • #include?<ace/OS.h>??
  • #include?<ace/Reactor.h>??
  • #include?<ace/SOCK_Connector.h>???
  • ??
  • #include?<string>??
  • #include?<iostream>??
  • using?namespace?std;??
  • ??
  • class?MyClient:public?ACE_Event_Handler???
  • {??
  • public:??
  • ????bool?open()??
  • ????{??
  • ????????ACE_SOCK_Connector?connector;??
  • ????????ACE_INET_Addr?addr(3000,"127.0.0.1");??
  • ????????ACE_Time_Value?timeout(5,0);??
  • ????????if(connector.connect(peer,addr,&timeout)?!=?0)??
  • ????????{??
  • ????????????cout<<endl<<"connecetd?fail";??
  • ????????????return?false;??
  • ????????}??
  • ????????ACE_Reactor::instance()->register_handler(this,ACE_Event_Handler::READ_MASK);??
  • ????????cout<<endl<<"connecetd?";??
  • ????????return?true;??
  • ????}??
  • ??
  • ????ACE_HANDLE?get_handle(void)?const??
  • ????{??
  • ????????return?peer.get_handle();??
  • ????}??
  • ??
  • ????int?handle_input?(ACE_HANDLE?fd)??
  • ????{??
  • ????????int?rev=0;??
  • ????????ACE_Time_Value?timeout(5,0);??
  • ????????if((rev=peer.recv(buffer,1000,&timeout))>0)??
  • ????????{??
  • ????????????buffer[rev]='\0';??
  • ????????????cout<<endl<<"rev:\t"<<buffer<<endl;??
  • ????????}??
  • ????????return?3;??
  • ????}??
  • ??
  • private:??
  • ????ACE_SOCK_Stream?peer;??
  • ????char?buffer[1024];??
  • };??
  • ??
  • int?main(int?argc,?char?*argv[])???
  • {??
  • ????MyClient?client;??
  • ????client.open();??
  • ??
  • ????while(true)??
  • ????{??
  • ????????ACE_Reactor::instance()->handle_events();???
  • ????}??
  • ??
  • ????return?0;???
  • }??
  • ?

    ?

    在這個(gè)例子中,客戶端連接上服務(wù)器后,通過(guò)ACE_Reactor::instance()->register_handler(this,ACE_Event_Handler::READ_MASK)注冊(cè)了一個(gè)讀就緒的回調(diào)函數(shù),當(dāng)服務(wù)器端給客戶端發(fā)消息的時(shí)候,會(huì)自動(dòng)觸發(fā)handle_input()函數(shù),將接收到的信息打印出來(lái)。

    這個(gè)例子只是為了演示反應(yīng)器的基本用法,并不完善,我將在下一節(jié)中對(duì)如何在Socket通信中使用反應(yīng)器做進(jìn)一步的介紹。


    ?

    在Socket編程中,常見(jiàn)的事件就是"讀就緒","寫(xiě)就緒",通過(guò)對(duì)這兩個(gè)事件的捕獲分發(fā),可以實(shí)現(xiàn)Socket中的異步操作。

    Socket編程中的事件處理器

    在前面我們已經(jīng)介紹過(guò),在ACE反應(yīng)器框架中,任何都必須派生自ACE_Event_Handler類,并通過(guò)重載其相應(yīng)會(huì)調(diào)事件處理函數(shù)來(lái)實(shí)現(xiàn)相應(yīng)的回調(diào)處理的。在Socket編程中,我們通常需要重載的函數(shù)有

  • handle_input()
    當(dāng)I/O句柄(比如UNIX中的文件描述符)上的輸入可用時(shí),反應(yīng)器自動(dòng)回調(diào)該方法。
  • handle_output()
    當(dāng)I/O設(shè)備的輸出隊(duì)列有可用空間時(shí),反應(yīng)器自動(dòng)回調(diào)該方法。
  • handle_close()
    當(dāng)事件處理器中的事件從Reactor中移除的時(shí)候調(diào)用。
  • 此外,為了使Reactor能通過(guò)I/O句柄找到對(duì)應(yīng)的事件處理器,還必須重載其get_handle()方法以使得Reactor建立起I/O句柄和事件處理器的關(guān)聯(lián)。

    使用Reactor框架。

    下面我們將以一個(gè)客戶端的程序?yàn)槔?#xff0c;介紹如何在Socket編程中使用Reactor框架。

    一.建立一個(gè)客戶端對(duì)象(事件處理器)。

    客戶端對(duì)象就是一個(gè)事件處理器,其聲明如下:

    ?

    Cpp代碼??
  • class?Client:public?ACE_Event_Handler??
  • {??
  • public:??
  • ????ACE_HANDLE?get_handle(void)?const;??
  • ????int?handle_input?(ACE_HANDLE?fd);??
  • ????int?handle_close?(ACE_HANDLE?handle,??
  • ACE_Reactor_Mask?close_mask);??
  • ????ACE_SOCK_Stream&?Peer();??
  • private:??
  • ????ACE_SOCK_Stream?peer;??
  • };??
  • ?

    ?

    Client端中我只關(guān)心"讀就緒"事件,故只重載了handle_input函數(shù)(大多數(shù)應(yīng)用下只需要重載handle_input函數(shù))。另外,在客戶端還保存了一個(gè)ACE_SOCK_Streampeer對(duì)象用來(lái)進(jìn)行Socket通信,同時(shí)封裝了一個(gè)Peer()函數(shù)返回它的引用。

    二.重載相應(yīng)回調(diào)處理函數(shù)

    ?

    Cpp代碼??
  • ACE_SOCK_Stream&?Client::Peer()??
  • {??
  • ????return?peer;??
  • }??
  • ??
  • ACE_HANDLE?Client::get_handle(void)?const??
  • {??
  • ????return?peer.get_handle();??
  • }??
  • ??
  • int?Client::handle_input?(ACE_HANDLE?fd)??
  • {??
  • ????int?rev=0;??
  • ????if((rev?=?peer.recv(buffer,1000))>0)??
  • ????{??
  • ????????buffer[rev]='\0';??
  • ????????cout<<endl<<"rev:\t"<<buffer<<endl;??
  • ????????return?0;??
  • ????}??
  • ????else????//Socket連接發(fā)生錯(cuò)誤,返回-1,在Reactor中注銷事件,觸發(fā)handle_close函數(shù)??
  • ????{??
  • ????????return?-1;??
  • ????}??
  • }??
  • ??
  • int?Client::handle_close?(ACE_HANDLE?handle,??
  • ?????????????????????????ACE_Reactor_Mask?close_mask)??
  • {??
  • ????cout<<endl<<"connecetd?closed";??
  • ????return?ACE_Event_Handler::handle_close(handle,close_mask);??
  • }??
  • ?

    ?

    幾個(gè)函數(shù)的功能都非常簡(jiǎn)單,這里就不多做介紹了。

    三.在Reactor中注冊(cè)事件

    首先讓我們來(lái)看看相應(yīng)的main函數(shù)的代碼:

    ?

    Cpp代碼??
  • int?main(int?argc,?char?*argv[])???
  • {??
  • ????Client?client;??
  • ????ACE_SOCK_Connector?connector;??
  • ????ACE_INET_Addr?addr(3000,"127.0.0.1");??
  • ????ACE_Time_Value?timeout(5,0);??
  • ????if(connector.connect(client.Peer(),addr,&timeout)?!=?0)??
  • ????{??
  • ????????cout<<endl<<"connecetd?fail";??
  • ????????return?0;??
  • ????}??
  • ??
  • ????ACE_Reactor::instance()->register_handler(&client,ACE_Event_Handler::READ_MASK);??
  • ??
  • while(true)??
  • {??
  • ACE_Reactor::instance()->handle_events();???
  • }??
  • ??
  • return?0;???
  • }??
  • ?

    ?

    在這里可以看到,使用Reactor框架后,依然首先通過(guò)ACE_SOCK_Connector的connect函數(shù)來(lái)建立連接。建立連接后,可以通過(guò)ACE_Reactor::instance()->register_handler函數(shù)來(lái)實(shí)現(xiàn)Reactor的注冊(cè),實(shí)現(xiàn)I/O事件和Client對(duì)象的handle_input方法相關(guān)聯(lián),它的第一個(gè)參數(shù)是事件處理器的地址,第二個(gè)參數(shù)是事件類型,由于這里只關(guān)心讀就緒事件,故注冊(cè)的事件類型是ACE_Event_Handler::READ_MASK

    四.啟動(dòng)Reactor事件循環(huán)

    通過(guò)如上設(shè)置后,我們就可以通過(guò)ACE_Reactor::instance()->handle_events()啟動(dòng)Reactor循環(huán)了,這樣,每當(dāng)服務(wù)器端有數(shù)據(jù)發(fā)送給客戶端時(shí),當(dāng)客戶端的數(shù)據(jù)就緒時(shí),就回觸發(fā)Client對(duì)象的handle_input函數(shù),將接收的數(shù)據(jù)打印出來(lái)。

    通常的做法是,將Reactor事件循環(huán)作為一個(gè)單獨(dú)的線程來(lái)處理,這樣就不會(huì)阻塞main函數(shù)。

    五.注銷Reactor事件

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

  • 隱式注銷。
    當(dāng)Reactor捕獲事件后,會(huì)觸發(fā)相應(yīng)的"handle_"處理函數(shù),當(dāng)"handle_"處理函數(shù)返回值大于或等于0時(shí),表示處理事件成功,當(dāng)返回值小于0時(shí),表示處理事件失敗,這時(shí)Reactor會(huì)自動(dòng)注銷該句柄所注冊(cè)的所有事件,并觸發(fā)handle_close函數(shù),以執(zhí)行相應(yīng)的資源清理工作。
    在本例中,當(dāng)handle_input函數(shù)里的recv函數(shù)接收到0個(gè)數(shù)時(shí),說(shuō)明socket發(fā)生錯(cuò)誤(大多為Socket連接中斷),此時(shí)返回-1,則系統(tǒng)自動(dòng)注銷相應(yīng)事件。
  • 顯示注銷。
    調(diào)用Reactor對(duì)象的remove_handler方法移除,它有兩個(gè)參數(shù),第一個(gè)是所注冊(cè)的事件反應(yīng)器對(duì)象,第二個(gè)是所要注銷的事件。
  • 在這個(gè)示例程序里,連接方只有一個(gè)Socket連接,Reactor的優(yōu)勢(shì)并沒(méi)有體現(xiàn)出來(lái),但在一些網(wǎng)絡(luò)管理系統(tǒng)里,連接方需要對(duì)多個(gè)需要管理的設(shè)備(服務(wù)器端)進(jìn)行連接,在這種情況下使用Reactor模式,只需要多開(kāi)一個(gè)Reactor事件循環(huán)線程就能實(shí)現(xiàn)事件多路分發(fā)復(fù)用,并且不會(huì)阻塞,通過(guò)面向?qū)ο蟮幕卣{(diào)方式管理,使用起來(lái)非常方便。

    Reactor框架的另外一個(gè)常用的地方就是服務(wù)器端,一般是一個(gè)服務(wù)器端對(duì)應(yīng)多個(gè)客戶端,這樣用Reactor模式能大幅提高并發(fā)能力,這方面的編程方法將在下一章給與介紹。


    ?

    在服務(wù)器端使用Reactor框架

    使用Reactor框架的服務(wù)器端結(jié)構(gòu)如下:

    服務(wù)器端注冊(cè)兩種事件處理器,ClientAcceptor和ClientService,ClientService類負(fù)責(zé)和客戶端的通信,每一個(gè)ClientService對(duì)象對(duì)應(yīng)一個(gè)客戶端的Socket連接。ClientAcceptor專門(mén)負(fù)責(zé)被動(dòng)接受客戶端的連接,并創(chuàng)建ClientService對(duì)象。這樣,在一個(gè)N個(gè)Socket連接的服務(wù)器程序中,將存在1個(gè)ClientAcceptor對(duì)象和N個(gè)ClientService對(duì)象。

    整個(gè)服務(wù)器端流程如下:

  • 首先創(chuàng)建一個(gè)ClientAcceptor對(duì)象,該對(duì)象在Reactor上注冊(cè)ACCEPT_MASK事件,Reactor將自動(dòng)在監(jiān)聽(tīng)端口建立Socket監(jiān)聽(tīng)。
  • 如果有對(duì)該端口的Socket連接時(shí),Reactor將自動(dòng)回調(diào)handle_input方法,ClientAcceptor重載此方法,并創(chuàng)建一個(gè)ClientService對(duì)象,用于處理和Client的通信。
  • ClientService對(duì)象根據(jù)服務(wù)器的具體功能實(shí)現(xiàn),其處理過(guò)程和客戶端程序類似,注冊(cè)相應(yīng)的回調(diào)事件并分發(fā)即可。
  • 代碼如下:

    ?

    Cpp代碼??
  • #include?<ace/OS.h>??
  • #include?<ace/Reactor.h>??
  • #include?<ace/SOCK_Connector.h>???
  • #include?<ace/SOCK_Acceptor.h>???
  • #include?<ace/Auto_Ptr.h>??
  • ??
  • class?ClientService?:?public?ACE_Event_Handler??
  • {??
  • public:??
  • ????ACE_SOCK_Stream?&peer?(void)?{?return?this->sock_;?}??
  • ??
  • ????int?open?(void)??
  • ????{??
  • ????????//注冊(cè)讀就緒回調(diào)函數(shù)??
  • ????????return?this->reactor?()->register_handler(this,?ACE_Event_Handler::READ_MASK);??
  • ????}??
  • ??
  • ????virtual?ACE_HANDLE?get_handle?(void)?const?{?return?this->sock_.get_handle?();?}??
  • ??
  • ????virtual?int?handle_input?(ACE_HANDLE?fd?)??
  • ????{??
  • ????????//一個(gè)簡(jiǎn)單的EchoServer,將客戶端的信息返回??
  • ????????int?rev?=?peer().recv(buf,100);??
  • ????????if(rev<=0)??
  • ????????????return?-1;??
  • ??
  • ????????peer().send(buf,rev);??
  • ????????return?0;??
  • ????}??
  • ??
  • ????//?釋放相應(yīng)資源??
  • virtual?int?handle_close?(ACE_HANDLE,?ACE_Reactor_Mask?mask)??
  • ????{??
  • ????????if?(mask?==?ACE_Event_Handler::WRITE_MASK)??
  • ????????????return?0;??
  • ????????mask?=?ACE_Event_Handler::ALL_EVENTS_MASK?|??
  • ????????????ACE_Event_Handler::DONT_CALL;??
  • ????????this->reactor?()->remove_handler?(this,?mask);??
  • ????????this->sock_.close?();??
  • ????????delete?this;????//socket出錯(cuò)時(shí),將自動(dòng)刪除該客戶端,釋放相應(yīng)資源??
  • ????????return?0;??
  • ????}??
  • ??
  • protected:??
  • ????char?buf[100];??
  • ????ACE_SOCK_Stream?sock_;??
  • };??
  • ??
  • class?ClientAcceptor?:?public?ACE_Event_Handler??
  • {??
  • public:??
  • ????virtual?~ClientAcceptor?(){this->handle_close?(ACE_INVALID_HANDLE,?0);}??
  • ??
  • ????int?open?(const?ACE_INET_Addr?&listen_addr)??
  • ????{??
  • ????????if?(this->acceptor_.open?(listen_addr,?1)?==?-1)??
  • ????????{??
  • ????????????ACE_OS::printf("open?port?fail");??
  • ????????????return?-1;??
  • ????????}??
  • ????????//注冊(cè)接受連接回調(diào)事件??
  • ????????return?this->reactor?()->register_handler(this,?ACE_Event_Handler::ACCEPT_MASK);??
  • ????}??
  • ??
  • ????virtual?ACE_HANDLE?get_handle?(void)?const??
  • ????{?return?this->acceptor_.get_handle?();?}??
  • ??
  • ????virtual?int?handle_input?(ACE_HANDLE?fd?)??
  • ????{??
  • ????????ClientService?*client?=?new?ClientService();??
  • ????????auto_ptr<ClientService>?p?(client);??
  • ??
  • ????????if?(this->acceptor_.accept?(client->peer?())?==?-1)??
  • ????????{??
  • ????????????ACE_OS::printf("accept?client?fail");??
  • ????????????return?-1;??
  • ????????}??
  • ????????p.release?();??
  • ????????client->reactor?(this->reactor?());??
  • ????????if?(client->open?()?==?-1)??
  • ????????????client->handle_close?(ACE_INVALID_HANDLE,?0);??
  • ????????return?0;??
  • ????}??
  • ??????
  • ????virtual?int?handle_close?(ACE_HANDLE?handle,??
  • ????????ACE_Reactor_Mask?close_mask)??
  • ????{??
  • ????????if?(this->acceptor_.get_handle?()?!=?ACE_INVALID_HANDLE)??
  • ????????{??
  • ????????????ACE_Reactor_Mask?m?=?ACE_Event_Handler::ACCEPT_MASK?|??
  • ????????????????ACE_Event_Handler::DONT_CALL;??
  • ????????????this->reactor?()->remove_handler?(this,?m);??
  • ????????????this->acceptor_.close?();??
  • ????????}??
  • ????????return?0;??
  • ????}??
  • ??
  • protected:??
  • ????ACE_SOCK_Acceptor?acceptor_;??
  • };??
  • ??
  • int?main(int?argc,?char?*argv[])???
  • {??
  • ????ACE_INET_Addr?addr(3000,"192.168.1.142");??
  • ????ClientAcceptor?server;??
  • ????server.reactor(ACE_Reactor::instance());??
  • ????server.open(addr);??
  • ??
  • ????while(true)??
  • ????{??
  • ????????ACE_Reactor::instance()->handle_events();???
  • ????}??
  • ??
  • ????return?0;???
  • }??
  • ?

    ?

    代碼功能比較簡(jiǎn)單,需要注意以下幾點(diǎn):

  • 這里注冊(cè)事件的方式和前面的文章中方式不一樣,是通過(guò)ACE_Event_Handler類的reactor()方法設(shè)置和獲取reactor的指針,比較直觀和方便。前面的文章是通過(guò)ACE_Reactor::instance()來(lái)獲取的一個(gè)單體reactor的指針。
  • 當(dāng)客戶端Socket連接關(guān)閉時(shí),需要釋放相應(yīng)資源,需要注意一下ClientService對(duì)象的handle_close方法中釋放資源的相應(yīng)代碼。

  • 定時(shí)器的實(shí)現(xiàn)

    通過(guò)Reactor機(jī)制,還可以很容易的實(shí)現(xiàn)定時(shí)器的功能,使用方式如下。

  • 編寫(xiě)一個(gè)事件反應(yīng)器,重載handle_timeout()方法,該方法是定時(shí)器的觸發(fā)時(shí)間到時(shí),會(huì)自動(dòng)觸發(fā)該方法。
  • 通過(guò)Reactor的schedule_timer()方法注冊(cè)定時(shí)器。
  • 啟動(dòng)reacotr的handle_events()事件分發(fā)循環(huán)。
  • 當(dāng)不想使用定時(shí)器時(shí),可以通過(guò)Reactor的cancel_timer()方法注銷定時(shí)器。
  • 下面的代碼簡(jiǎn)單的實(shí)現(xiàn)了一個(gè)定時(shí)器,并具有基本的開(kāi)啟,關(guān)閉功能。

    ?

    Cpp代碼??
  • #include?<ace/OS.h>??
  • #include?<ace/Reactor.h>??
  • ??
  • class?MyTimerHandler?:?public?ACE_Event_Handler??
  • {??
  • private:??
  • ????int?inteval;????//執(zhí)行時(shí)間間隔??
  • ????int?delay;????????//延遲執(zhí)行時(shí)間??
  • ????int?timerid;??
  • ??
  • public:??
  • ????MyTimerHandler(int?delay,int?inteval)??
  • ????{??
  • ????????this->delay=delay;??
  • ????????this->inteval=inteval;??
  • ????}??
  • ??
  • ????int?open()????//注冊(cè)定時(shí)器??
  • ????{??
  • ????????ACE_Time_Value?delaytime(inteval);??
  • ????????ACE_Time_Value?intevaltime(inteval);??
  • ????????timerid?=?reactor()->schedule_timer(this,??
  • ????????????0,????//傳遞handle_timeout給的參數(shù)??
  • ????????????delaytime,??
  • ????????????intevaltime);??
  • ????????return?timerid;??
  • ????}??
  • ??
  • ????int?close()????//取消定時(shí)器??
  • ????{??
  • ????????return?reactor()->cancel_timer(timerid);??
  • ????}??
  • ??
  • ????//定時(shí)器回調(diào)函數(shù)??
  • ????int?handle_timeout?(const?ACE_Time_Value?&current_time,??
  • ????????const?void?*?=?0)??
  • ????{??
  • ????????time_t?epoch?=?((timespec_t)current_time).tv_sec;??
  • ????????ACE_DEBUG?((LM_INFO,??
  • ????????????ACE_TEXT?("handle_timeout:?%s\n"),??
  • ????????????ACE_OS::ctime?(&epoch)));??
  • ????????return?0;??
  • ????}??
  • };??
  • ??
  • int?main(int?argc,?char?*argv[])???
  • {??
  • ????MyTimerHandler?*?timer?=?new?MyTimerHandler?(3,5);??
  • ????timer->reactor(ACE_Reactor::instance());??
  • ????timer->open();??
  • ??
  • ????for(int?i=0;i<2;i++)????//觸發(fā)次handle_timeout事件??
  • ????{??
  • ????????ACE_OS::printf("\n%d\n",i);??
  • ????????ACE_Reactor::instance()->handle_events();??
  • ????}??
  • ??
  • ????timer->close();??
  • ????ACE_OS::printf("cancel?timer");??
  • ????while(true)??
  • ????????ACE_Reactor::instance()->handle_events();??
  • ????return?0;???
  • }??
  • ?

    ?

    代碼功能比較簡(jiǎn)單,這里就不多做介紹了。

    總結(jié)

    以上是生活随笔為你收集整理的ACE反应器(Reactor)模式的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。