ACE事件处理器

来源:互联网 发布:php和c语言哪个难 编辑:程序博客网 时间:2024/06/06 13:58

      下面的例子创建了两个具体事件处理器。第一个具体事件处理器My_Accept_Handler用于接受和建立从客户到来的连接。另一个事件处理器是My_Input_Handler,它用于在连接建立后对连接进行处理。因而,My_Accept_Handler接受连接,并将实际的处理委托给My_Input_Handler

#include "ace/Reactor.h"#include "ace/SOCK_Acceptor.h"#include "ace/Log_Msg.h"   //ace_debug 
typedef ACE_SOCK_Acceptor Acceptor;class My_Input_Handler: public ACE_Event_Handler{public:My_Input_Handler()  //Constructor{qDebug()<<"input_handler constructor...";memset(data,0,sizeof(data));}//来自I/O设备的输入。当I/O句柄(比如UNIX中的文件描述符)上的输入可用时,反应堆自动回调该方法。int handle_input(ACE_HANDLE){peer_.recv_n(data,10);qDebug()<<data;//ACE_Addr local_addr,remote_addr;//peer_.get_local_addr(local_addr);//peer_.get_remote_addr(remote_addr);return 0;}//Used by the reactor to determine the underlying handleACE_HANDLE get_handle() const{return this->peer_.get_handle();}//Returns a reference to the underlying stream.ACE_SOCK_Stream &peer_i(){return this->peer_;}private:ACE_SOCK_Stream peer_;   //用于提供基于TCP协议的服务,派生于ACE_SOCK_IOchar data [11];};class My_Accept_Handler: public ACE_Event_Handler{public:My_Accept_Handler(ACE_Addr &addr){qDebug()<<"accept_handler constructor...";this->open(addr);}int open(ACE_Addr &addr){qDebug()<<"accept_handler listen...";peer_acceptor.open(addr);return 0;}//一旦有连接请求则调用此函数int handle_input(ACE_HANDLE handle){ACE_INET_Addr addr_client;//Client has requested connection to server.//Create a handler to handle the connectionMy_Input_Handler *eh= new My_Input_Handler();//Accept the connection ”into” the Event Handlerif (this->peer_acceptor.accept (eh->peer_i(), // stream&addr_client, // remote address0, // timeout1) ==-1) //restart if interrupted{qDebug()<<"error in connection...";return 0;}//qDebug()<<addr_client.get_host_name()<<":"<<addr_client.get_port_number()<<" established...";ACE_TCHAR buf[256]={0};int ret=addr_client.addr_to_string(buf,sizeof(buf),1);qDebug()<<buf<<" established...";//Register the input event handler for readingACE_Reactor::instance()->register_handler(eh,ACE_Event_Handler::READ_MASK);//Unregister as the acceptor is not expecting new clients//return -1;return 0;}//Used by the reactor to determine the underlying handleACE_HANDLE get_handle(void) const{return this->peer_acceptor.get_handle();}private:Acceptor peer_acceptor;};int main(int argc, char * argv[]){//Create an address on which to receive connectionsACE_INET_Addr addr(PORT_NO);//Create the Accept Handler which automatically begins to “listen”//for client requests for connectionsMy_Accept_Handler *eh=new My_Accept_Handler(addr);//Register the reactor to call back when incoming client connectsACE_Reactor::instance()->register_handler(eh,ACE_Event_Handler::ACCEPT_MASK);//Start the event loopwhile(1)ACE_Reactor::instance()->handle_events();}

  在上面的例子中,首先创建了一个ACE_INET_Addr地址对象,将我们希望在其上接受连接的端口作为参数传给它。其次,实例化一个类型为My_Accept_Handler的对象。随后地址对象通过My_Accept_Handler的构造器传递给它。My_Accept_Handler有一个用于连接建立的底层“具体接受器”(在讲述“IPC”的一章中有与具体接受器相关的内容)。My_Accept_Handler的构造器将对新连接的“侦听”委托给该具体接受器的open()方法。在处理器开始侦听连接后,它在反应堆上登记,通知说在接收到新连接请求时,它需要被回调。为完成此操作,我们采用ACE_Event_Handler::ACCEPT_MASK掩码调用register_handler()

  当反应堆被告知要登记处理器时,它执行“双重分派”来确定事件处理器的底层句柄。为完成此操作,它调用get_handler()方法。因为反应堆使用get_handle()方法来确定底层流的句柄,在My_Accept_Handler中必须实现get_handle()方法。在此例中,我们简单地调用具体接受器的get_handle(),它会将适当的句柄返回给反应堆。

  一旦在该句柄上接收到新的连接请求,反应堆会自动地回调My_Accept_Handlerhandle_input()方法。随后Accept Handler(接受处理器)实例化一个新的Input Handler(输入处理器),并调用具体接受器的accept()方法来实际地建立连接。注意Input Handler底层的流是作为accept()调用的第一个参数传入的。这使得新实例化的Input Handler中的流被设置为在连接建立(由accept()完成)后立即创建的新流。随后Accept HandlerInput Handler登记到反应堆,通知它如果有任何可读的输入就进行回调(使用ACE_Event_Handler::READ_MASK)。随后接受处理器返回-1,使自己从反应堆的内部事件分派表中被拆除。

  现在如果有任何输入从客户到达,反应堆将自动回调My_Input_Handler::handle_input()。注意在My_Input_Handlerhandle_input()方法中,返回给反应堆是0。这指示我们希望保持它的登记;反之在My_Accept_Handler中我们在它的handle_input()中返回-1,以确保它被注销。

来自:http://docs.huihoo.com/ace_tao/ACE-2002-12/Part-Two/Chapter-6.htm



0 0