zoukankan      html  css  js  c++  java
  • ACE Reactor模型学习

    ACE Reactor框架可以用事件驱动的方式来处理网络化的操作,也可以用来处理信号和实现定时器的功能.在非Windows平台上,其默认用select模型实现(实现类为:ACE_Select_Reactor);在Windows平台上利用WSAEventSelect模型实现(实现类为:ACE_WFMO_Reactor). 其主要角色包括:

    ACE_Reactor:在Reactor框架中管理事件处理器,执行其事件循环来驱动事件检测、多路分离等功能.

    ACE_Event_Handler:ACE_Reactor回调的目标,其定义了各种挂钩方法以供ACE_Reactor回调处理.

    示例:

    /*
    *  网络数据读取发送操作的封装
    */
    class  CClientSocketHandler : public ACE_Event_Handler
    {
    private:
        ACE_SOCK_Stream   m_stream;                          
    //流对象
        ACE_TCHAR  m_szName[MAXHOSTNAMELEN];    //保存连接上的主机名

    public:
        ACE_SOCK_Stream
    &  Peer()
        {
            
    return this->m_stream;
        }

        
    virtual ACE_HANDLE get_handle (voidconst
        {
            
    return this->m_stream.get_handle();
        }

        
    int  Init( )
        {
            ACE_INET_Addr  addrRemote;
            
    ifthis->m_stream.get_remote_addr( addrRemote ) == 0 )  //获取连接的远程地址
            {
                
    if( addrRemote.addr_to_string( m_szName, sizeof( ACE_TCHAR) * _countof( m_szName ) ) == 0 )
                {
                    ACE_DEBUG(( LM_DEBUG, ACE_TEXT(
    "%s connected!\n"), m_szName ));
                }
            }
            
    //向反应器登记,这里只登记为读操作以求简便
            return  this->reactor()->register_handler( this, ACE_Event_Handler::READ_MASK );
        }

        
    virtual int handle_input ( ACE_HANDLE )
        {
            
    //此时在网络连接上有数据可以读取
            char szBuffer[4096];
            ssize_t  nRecv 
    = 0;
            nRecv  
    =  this->m_stream.recv( szBuffer, _countof(szBuffer) );
            
    if( nRecv <= 0 )
            {
                ACE_DEBUG(( LM_DEBUG, ACE_TEXT(
    "%s connection closed\n"), m_szName ));
                
    return -1;
            }

            szBuffer[nRecv] 
    = '\0';
            
    //显示读取数据
            ACE_DEBUG(( LM_DEBUG, ACE_TEXT("recv from:%s   msg:%s\n"), m_szName, ACE_TEXT_CHAR_TO_TCHAR(szBuffer) ));

            
    return 0;
        }

        
    virtual int handle_close ( ACE_HANDLE handle,     ACE_Reactor_Mask close_mask )
        {
            
    //指定DONT_CALL,表示解除登记时不需要调用该事件处理器的handle_close方法
            ACE_Reactor_Mask  mask =  ACE_Event_Handler::READ_MASK | ACE_Event_Handler::DONT_CALL;
            
    this->reactor()->remove_handler( this, mask );   //解除登记
            this->m_stream.close();  //关闭流对象
            delete this;   //销毁自己
            return 0;
        }
    };


    /*
    * 接受连接处理类
    */
    class  CClientSocketAccept : public ACE_Event_Handler
    {
    private:
        ACE_SOCK_Acceptor  m_acceptor;

    public:
        
    virtual ~CClientSocketAccept()
        {
            
    this->handle_close( ACE_INVALID_HANDLE, 0 );
        }

        
    int  Init( const ACE_INET_Addr& addr )
        {
            
    ifthis->m_acceptor.open( addr, 1 ) == -1 )
            {
                
    int n = errno;
                ACE_ERROR_RETURN(( LM_ERROR, ACE_TEXT(
    "ACE_SOCK_Acceptor.open() Failed")), -1 );
            }
            
    return this->reactor()->register_handler( this, ACE_Event_Handler::ACCEPT_MASK );
        }

        
    virtual ACE_HANDLE get_handle (voidconst
        {
            
    return m_acceptor.get_handle();
        }

        
    virtual int handle_input ( ACE_HANDLE handle = ACE_INVALID_HANDLE )
        {
            
    //有新的连接来到了
            CClientSocketHandler  *pSockHandler  =  NULL;
            ACE_NEW_RETURN( pSockHandler, CClientSocketHandler, 
    -1 );

            
    ifthis->m_acceptor.accept( pSockHandler->Peer() ) == -1 )
            {
                delete pSockHandler;
                ACE_ERROR_RETURN(( LM_ERROR, ACE_TEXT(
    "ACE_SOCK_Acceptor.accept() Failed")), -1 );
            }

            pSockHandler
    ->reactor( this->reactor() );
            
    if( pSockHandler->Init() == -1 )
            {
                pSockHandler
    ->handle_close( ACE_INVALID_HANDLE, 0 );
            }

            
    return 0;
        }

        
    virtual int handle_close ( ACE_HANDLE ,     ACE_Reactor_Mask )
        {
            
    if ( this->m_acceptor.get_handle() != ACE_INVALID_HANDLE )
            {
                ACE_Reactor_Mask  mask 
    =  ACE_Event_Handler::ACCEPT_MASK | ACE_Event_Handler::DONT_CALL;
                
    this->reactor()->remove_handler( this, mask );
                
    this->m_acceptor.close();
            }
            
    return 0;
        }
    };
    ///////////////////////////////////////////////////////////////////////////////////////////////////////
        //监听9981端口,循环处理客户端连接
        ACE_INET_Addr  addr( 9981 );  //监听9981端口

        ACE_Reactor
    * pReactor =  ACE_Reactor::instance();

        CClientSocketAccept  acceptor;
        acceptor.reactor( pReactor );

        
    if( acceptor.Init( addr ) == -1 )
        {
            
    return -1;
        }

        pReactor
    ->run_reactor_event_loop();
  • 相关阅读:
    Mysql_大字段问题Row size too large.....not counting BLOBs, is 8126.
    Pycharm快捷键设置(鼠标滚动控制字体大小)
    python实现将base64编码的图片下载到本地
    [CentOS_7.4]Linux编译安装ffmpeg
    contenOs7
    文本特征提取方法研究
    Mahout中相似度计算方法介绍
    基于Mahout的电影推荐系统
    向Python女神推荐这些年我追过的经典书籍
    Mahout推荐算法API详解
  • 原文地址:https://www.cnblogs.com/fangkm/p/1526196.html
Copyright © 2011-2022 走看看