下面的例子创建了两个具体事件处理器。第一个具体事件处理器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 handle
ACE_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_IO
char 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 connection
My_Input_Handler *eh= new My_Input_Handler();
//Accept the connection ”into” the Event Handler
if (this->peer_acceptor.accept (eh->peer_i(), // stream
&addr_client, // remote address
0, // timeout
1) ==-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 reading
ACE_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 handle
ACE_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 connections
ACE_INET_Addr addr(PORT_NO);
//Create the Accept Handler which automatically begins to “listen”
//for client requests for connections
My_Accept_Handler *eh=new My_Accept_Handler(addr);
//Register the reactor to call back when incoming client connects
ACE_Reactor::instance()->register_handler(eh,ACE_Event_Handler::ACCEPT_MASK);
//Start the event loop
while(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_Handler的handle_input()方法。随后Accept Handler(接受处理器)实例化一个新的Input Handler(输入处理器),并调用具体接受器的accept()方法来实际地建立连接。注意Input Handler底层的流是作为accept()调用的第一个参数传入的。这使得新实例化的Input Handler中的流被设置为在连接建立(由accept()完成)后立即创建的新流。随后Accept Handler将Input Handler登记到反应堆,通知它如果有任何可读的输入就进行回调(使用ACE_Event_Handler::READ_MASK)。随后接受处理器返回-1,使自己从反应堆的内部事件分派表中被拆除。
现在如果有任何输入从客户到达,反应堆将自动回调My_Input_Handler::handle_input()。注意在My_Input_Handler的handle_input()方法中,返回给反应堆是0。这指示我们希望保持它的登记;反之在My_Accept_Handler中我们在它的handle_input()中返回-1,以确保它被注销。
来自:http://docs.huihoo.com/ace_tao/ACE-2002-12/Part-Two/Chapter-6.htm