ACE笔记(3) -用ACE_Reactor 实现SOCKET事件处理

本文详细介绍了使用ACE_Reactor机制实现SOCKET事件处理的方法。包括关键类ACE_Event_Handler的使用,如实现handle_signal和get_handle方法,以及如何利用ACE_Reactor进行事件注册、挂起、恢复和移除。并通过一个简单的SOCKET SERVER实例,展示了如何设置连接和数据读取事件。

 

ACE_Reactor 反射机制 ACE_Reactor 实现SOCKET事件处理
 
 
所有需要事件处理的类须继承 ACE_Event_Handler 类,
 
并实现handle_signal方法,如果必要则要实现 get_handle 方法,表明事件触发对象是什么
 
handle_signal方法返回-1时,会调用handle_close方法
 
 
通过 ACE_Reactor register_handler方法使事件处理对象同事件触发对象( ACE_Event )关联起来
 
 register_handler
方法有以下3种常用调用方式
 
1 virtual int register_handler (ACE_Event_Handler *event_handler,
                                 
ACE_Reactor_Mask mask);
                                 
 
表为I/O事件注册事件通知
  I
/O事件触发的来源由 get_handle()方法提供
 
该方法会调用ACE_Event_Handler::add_reference()方法,如果当前事件注册通知没有被注册
 
 
2 virtual int register_handler (ACE_HANDLE io_handle,
                               
ACE_Event_Handler *event_handler,
                               
ACE_Reactor_Mask mask);
 
方法2同方法1类似,但无需提供 get_handle()方法
 
 
3virtual int register_handler (ACE_Event_Handler *event_handler,
                                 ACE_HANDLE event_handle
= ACE_INVALID_HANDLE);
 
只能使用在WIN平台
 
ACE_Eventhandle()返回事件处理句柄ACE_HANDLE
 
 
要使触发事件正常运行,要执行 ACE_Reactor 的事件处理方法 handle_events(time),
 
不加time参数,则不会出现超时退出现象,除非调用了了ACE_Reactorclose方法
 
 
还可以利用ACE_Reactor
      resume_handler
      suspend_handler
     
方法挂起和恢复事件通知
     
当然也可以使用remove_handler彻底删除事件通知

下面通过实例(来自ACE自带的例子,稍有改动)讲解如何利用ACE事件机制处理SOCKET I/O请求实现一个简单的SOCKET SERVER
 
涉及到以下主要系统类
 
ACE_INET_Addr
   
网络地址类
   
其有多个构造函数,常见构造如下:
     
ACE_INET_Addr (u_short port_number,ACE_UINT32 ip_addr = INADDR_ANY);
   
ACE_INET_Addr (u_short port_number,const char host_name[],int address_family = AF_UNSPEC);
     ACE_EXPLICIT
ACE_INET_Addr (const char address[]);
 
ACE_SOCK_Acceptor
   SOCKET
接收器类,常用构造:
     
ACE_SOCK_Acceptor (const ACE_Addr &local_sap,
                     
int reuse_addr = 0,
                     
int protocol_family = PF_UNSPEC,
                     
int backlog = ACE_DEFAULT_BACKLOG,
                     
int protocol = 0);
   
参数reuse_addr 1表地址重用
   
其主要有如下方法:
    open
方法
    accept
方法  
 
ACE_SOCK_Stream
   SOCKET
流处理类,该类可由ACE_SOCK_Acceptoraccept方法赋予实在的内容
   
提供有recv sendclose等方法
   
 
ACE_Event_Handler
   
事件处理类
   
提供了一些事件触发时回调的一些方法的定义
   
 
基本实现思路:
 
在连接上设置事件触发机制和在接收后的数据读入上设置事件触发机制

 
源码如下:
#include "ace/Reactor.h"
#include "ace/WFMO_Reactor.h"
#include "ace/INET_Addr.h"
#include "ace/SOCK_Stream.h"
#include "ace/SOCK_Acceptor.h"
#include "ace/OS_main.h"

ACE_RCSID
(WFMO_Reactor, Network_Events, "Network_Events.cpp,v 4.3 2003/11/05 09:36:08 jwillemsen Exp")

//数据读入时的事件处理类
class Network_Handler : public ACE_Event_Handler
{
public:
 
virtual int handle_input (ACE_HANDLE handle);
 
virtual int handle_close (ACE_HANDLE handle,
                           
ACE_Reactor_Mask close_mask);
 
virtual ACE_HANDLE  get_handle (void) const;
 
//数据读入时的事件触发对象
 
ACE_SOCK_Stream stream_;

};

ACE_HANDLE
Network_Handler::get_handle (void) const
{
 
return this->stream_.get_handle ();
}

int
Network_Handler::handle_input (ACE_HANDLE handle)
{
  ACE_DEBUG
((LM_DEBUG, "Network_Handler::handle_input handle = %d/n", handle));

 
while (1)
   
{
     
char message[BUFSIZ];
     
int result = this->stream_.recv (message, sizeof message);
     
if (result > 0)
       
{
          message
[result] = 0;
          ACE_DEBUG
((LM_DEBUG, "Remote message: %s/n", message));
       
}
     
else if (result == 0)
       
{
          ACE_DEBUG
((LM_DEBUG, "Connection closed/n"));
         
//注意,要返回-1,以便handle_close执行
         
return -1;
       
}
     
else if (errno == EWOULDBLOCK)
       
{
         
return 0;
       
}
     
else
       
{
          ACE_DEBUG
((LM_DEBUG, "Problems in receiving data, result = %d", result));
         
return -1;
       
}
   
}
}

int
Network_Handler::handle_close (ACE_HANDLE handle,
                               
ACE_Reactor_Mask)
{
  ACE_DEBUG
((LM_DEBUG, "Network_Handler::handle_close handle = %d/n", handle));
 
//注意:一定要调用close方法,不然你会发现在连接了4000个以上客户的时候,程序会变的越来越慢的
 
this->stream_.close ();
 
return 0;
}

//客户连接时的事件处理类
class Network_Listener : public ACE_Event_Handler
{
public:
 
Network_Listener (void);
 
// Default constructor
 
~Network_Listener (void);
 
// Default constructor

 
virtual int handle_input (ACE_HANDLE handle);
 
virtual int handle_close (ACE_HANDLE handle,
                           
ACE_Reactor_Mask close_mask);
  ACE_HANDLE get_handle
(void) const;

 
ACE_INET_Addr local_address_;
 
//客户连接时的事件触发对象
 
ACE_SOCK_Acceptor acceptor_;
 
Network_Handler *handler;
};

Network_Listener::Network_Listener (void)
 
: local_address_ (ACE_DEFAULT_SERVER_PORT),
    acceptor_
(local_address_, 1)
{
 
this->reactor (ACE_Reactor::instance ());
 
//向reactor注册连接事件
 
int result = this->reactor ()->register_handler (this,ACE_Event_Handler::ACCEPT_MASK);
  ACE_ASSERT
(result == 0);
 
  handler
=new Network_Handler();
 
}

Network_Listener::~Network_Listener (void)
{
}

ACE_HANDLE
Network_Listener::get_handle (void) const
{
 
return this->acceptor_.get_handle ();
}

int
Network_Listener::handle_input (ACE_HANDLE handle)
{
  ACE_DEBUG
((LM_DEBUG, "Network_Listener::handle_input handle = %d/n", handle));

 
ACE_INET_Addr remote_address;
 
ACE_SOCK_Stream stream;

 
// 尝试重新关联事件
 
int reset_new_handle = this->reactor ()->uses_event_associations ();

 
int result = this->acceptor_.accept (stream, // stream
                                       
&remote_address, // 远端地址
                                       
0, // 超时设置
                                       
1, // 重用地址
                                       reset_new_handle
);  // reset new handler
  ACE_ASSERT
(result == 0);

  ACE_DEBUG
((LM_DEBUG, "Remote connection from: "));
  remote_address
.dump ();
  handler
->stream_=stream;
  result
= this->reactor ()->register_handler (handler,READ_MASK);
  ACE_ASSERT
(result == 0);
 
return 0;
}

int
Network_Listener::handle_close (ACE_HANDLE handle,
                               
ACE_Reactor_Mask)
{
  ACE_DEBUG
((LM_DEBUG, "Network_Listener::handle_close handle = %d/n", handle));

 
this->acceptor_.close ();

 
delete this;

 
return 0;
}

int
ACE_TMAIN
(int, ACE_TCHAR *[])
{
 
Network_Listener *listener =
   
new Network_Listener;
 
//开始循环事件处理
 
ACE_Reactor::run_event_loop ();

 
return 0;
};  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值