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

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()方法
  
  3、virtual int register_handler (ACE_Event_Handler *event_handler,
                                 ACE_HANDLE event_handle = ACE_INVALID_HANDLE);
  只能使用在WIN平台
  (ACE_Event的handle()返回事件处理句柄ACE_HANDLE)
 
 要使触发事件正常运行,要执行 ACE_Reactor 的事件处理方法 handle_events(time),
 不加time参数,则不会出现超时退出现象,除非调用了了ACE_Reactor的close方法
 
 还可以利用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_Acceptor的accept方法赋予实在的内容
   提供有recv 、send、close等方法
   
  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;
};   

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
ACE Reactor是一个用于事件驱动的框架,主要用于处理异步事件。它的接口声明放在Reactor.h中,接口的实现分别放在Reactor.cpp和Reactor.ini文件中,而Reactor.inl作为内联函数直接在Reactor.h文件中包含了。其内部实现主要封装在ACE_Reactor_Impl类中 。 在ACE_Select_Reactor_Notify类中,有一个指向ACE_Select_Reactor的指针select_reactor_。如果该指针为空,那么Reactor管理器将不支持Notify事件 。 ACE_Reactor类中的run_reactor_event_loop方法用于处理事件的循环。它会调用handle_events方法,该方法是由ACE_Reactor_Impl对象指针中的成员函数实现的。handle_events的作用是在超时时间到或事件触发时才返回,并返回ACE_Event_Handlers派发的总数。与altertable_handle_events不同的是,在eventloop中,当系统将一个I/O完成例程或一个异步过程调用排队时才会返回。eventloop指的是run_reactor_event_loop方法中的while(1)的循环 。 综上所述,ACE Reactor是一个用于处理事件驱动的框架,它通过封装不同的实现来提供事件处理和调度的功能,并支持异步事件处理。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [ACE_Reactor(一)整体理解ACE_Reactor](https://blog.csdn.net/chinaclock/article/details/49021839)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值