zoukankan      html  css  js  c++  java
  • ACE-Reactor框架

    Reactor是一种事件驱动型构架,ACE_Reactor模式减轻了程序员对底层网络IO事件监视的负担,一般情况下程序员只要继承ACE_Event_Handler类,重写相关的接口处理函数,然后向ACE_Reactor的对象注册相关事件即可,事件的定义在ACE_Event_Handler类中有相关定义。

    研究Reactor先研究一下C++的桥接模式:

    设计模式一:桥接模式的定义:将抽象化(Abstraction)与实现化(Implementation)分离,使得二者可以独立地变化。

     

    设计模式二:Facade设计模式,定义了用于应用程序访问ACE_Reactor框架的接口,为不同同步类型的管理器提供数据成员和统一的接口

    管理器:

    ACE_Dev_Poll_Reactor:  基于poll调用的Reactor管理器

    ACE_Select_Reactor_T:  基于select调用的Reactor管理器

    ACE_WFMO_Reactor:     基于WaitForMultipleObjects调用的Reactor管理器

    ACE_TP_Reactor:          基于select调用,采用线程池调度的Reactor管理器

    Reactor框架:

    先上ACE_Event_Handler

    ACE_Event_Handler_T

    Enable a class that doesn't inherit from the ACE_Event_Handler to be incorporated into the ACE_Reactor framework. Thanks to Greg Lavender (g.lavender@isode.com) for sharing this idea.

    It is sometimes the case that an application has a hierarchy of operation dispatcher classes that have their own inheritance hierarchy but also would like to integrate with the ACE_Reactor. Rather than adopt a "mixin" approach, it is often cleaner to define a template as a subclass of ACE_Event_Handler and paramterize it with an operation dispatcher type. When constructing an instantiation of the ACE_Event_Handler_T object, a set of pointers to member functions must be provided so that when one of the handle_* methods is called by the ACE_Reactor, the appropriate method is called on the underlying operations object. This is done since in some cases it is useful to map any event that happens to the same method on an object. The ACE_Event_Handler_T template is instantiated by an operations object and registered with the ACE_Reactor, and it then calls the appropriate op_handler. So, it's basically just another level of indirection in event dispatching. The coupling betweent the ultimate handler of the event and the ACE_Event_Handler class is relaxed a bit by have this intermediate <op_handler_> object of type <T> around. The client object can then dynamically change the bindings for the various handlers so that during the life of one of the operation objects, it can change how it wants events to be handled. It just instantiates a new instance of the template with different bindings and reregisters this new object with the ACE_Reactor.

    (摘自http://doc.uh.cz/C_C%2B%2B/ACE/ace/classACE__Event__Handler__T.html#_details)简单的说就是实现了不同类的方法也可以融合到ACE_Reactor 中进行调用。

    实例:(书本的常规方法实现)

    Handle_Data.h

    #include "ace/Event_Handler.h"
    #include "ace/SOCK_Stream.h"
    #include "ace/INET_Addr.h"
    #include "ace/Reactor.h"
    #include "ace/Time_Value.h"
    
    class Handle_data: public ACE_Event_Handler
    {
        public:        
            Handle_data( ACE_Reactor *r = ACE_Reactor::instance() ):ACE_Event_Handler(r)  {}
            ACE_INT32 open( );
            ACE_INT32 handle_input( ACE_HANDLE = ACE_INVALID_HANDLE );
            ACE_INT32 handle_close( ACE_HANDLE = ACE_INVALID_HANDLE, ACE_Reactor_Mask mask = 0 );
            
            ACE_HANDLE get_handle( ) const
            {
                return peer_.get_handle();
            }
            ACE_SOCK_Stream &get_peer()
            {
                return peer_;
            }
        private:    
            ~Handle_data(){ACE_DEBUG( (LM_DEBUG, "handle data ~dctor .
    ") );};
        private:    
            ACE_SOCK_Stream  peer_;        
    };

    Handle_Data.cpp

    #include "ace/SOCK_Stream.h"
    #include "ace/Reactor.h"
    #include "ace/Event_Handler.h"
    #include "ace/Log_Msg.h"
    #include "ace/Timer_Queue.h"
    #include "handle_data.h"
    
    ACE_INT32 Handle_data::open( )
    {    
        ACE_INT32 ret = 0;
        ACE_INET_Addr remote_addr;    
        get_peer().get_remote_addr( remote_addr );        
        ACE_DEBUG( (LM_DEBUG, "the remote addr is %s
    ", remote_addr.get_host_addr())  );
        
        ret = reactor()->register_handler( this, ACE_Event_Handler::READ_MASK );
        if (ret != -1)    
        {        
            ACE_DEBUG( (LM_DEBUG, "handle data register ok!
    ")  );        
        }    
        return ret;
    }
    
    ACE_INT32 Handle_data::handle_close( ACE_HANDLE , ACE_Reactor_Mask )
    {    
        get_peer().close();
        ACE_DEBUG( (LM_DEBUG, "handle data close.
    ") );
        delete this;
        return 0;
    }
    
    ACE_INT32 Handle_data::handle_input( ACE_HANDLE )
    {    
        ACE_INT8 buf[512] = {0};
        ACE_INT32 len;
          
        len = get_peer().recv( buf, 500);
        if (len > 0)
        {
            ACE_DEBUG( (LM_DEBUG, "recv data %s, len:%d.
    ", buf, len) );        
            return 0;
        }
        else if (len == 0)
        {
            ACE_DEBUG( (LM_DEBUG, "recv data len is 0, client exit.
    ") );
            return -1;
        }
        else
        {
            ACE_DEBUG( (LM_DEBUG, "recv data error len < 0" ) );
            return -1;
        }    
    }
  • 相关阅读:
    yii2美化url
    Android 百度地图API 定位 导航
    辛星浅谈PHP的混乱的编码风格
    html5非常火,他究竟与html4有何差别?
    Cocos2d-x 3.0心得(01)-图片载入与混合模式
    解读BOM与COM
    HDU 1718 Rank counting sort解法
    汉语转拼音pinyin4j
    UVALive-6656-Watching the Kangaroo(二分)
    thinPHP中多维数组的遍历
  • 原文地址:https://www.cnblogs.com/jackcin/p/4121596.html
Copyright © 2011-2022 走看看