ACE事件处理器

      下面的例子创建了两个具体事件处理器。第一个具体事件处理器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_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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值