• Acceptor模型和Connector模型学习


    前面学习ACE Reactor模型的时候写了CClientSocketAccept 类来处理客户端的连接,在接收到连接后用CClientSocketHandler来处理数据的发送和接收.现在将CClientSocketHandler类作为模板参数传递,同时也将真正接收连接操作的ACE_SOCK_Acceptor类作为模板参数传递,重构后如下:
    /*
    * 接受连接处理类
    */
    template
    < typename TSocketHandler, typename TAcceptor >
    class  CClientSocketAcceptT : public ACE_Event_Handler
    {
    private:
        TAcceptor  m_acceptor;

    public:
        
    virtual ~CClientSocketAcceptT()
        {
            
    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 )
        {
            
    //有新的连接来到了
            TSocketHandler  *pSockHandler  =  NULL;
            ACE_NEW_RETURN( pSockHandler, TSocketHandler, 
    -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;
        }
    };

    typedef CClientSocketAcceptT
    <CClientSocketHandler,ACE_SOCK_Acceptor>  CClientSocketAccept;
    于是Acceptor模型就已显现雏形了.改进之处在于消除了接收器和服务处理器之间的耦合.下面用Acceptor模型写个示例:
    /*
    *  网络数据读取发送操作的封装
    */
    class  CClientSocketHandler2 : public ACE_Svc_Handler<ACE_SOCK_Stream,ACE_NULL_SYNCH>
    {
    private:
        typedef  ACE_Svc_Handler
    <ACE_SOCK_Stream,ACE_NULL_SYNCH>  super;

        ACE_TCHAR  m_szName[MAXHOSTNAMELEN];    
    //保存连接上的主机名

    public:
        
    virtual int open (void *= 0)
        {
            
    if( super::open( p ) == -1 )  //父类open方法默认向反应器注册READ_MASK事件
                return -1;

            ACE_INET_Addr  addrRemote;
            
    ifthis->peer().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 0;
        }

        
    virtual int handle_input ( ACE_HANDLE )
        {
            
    //此时在网络连接上有数据可以读取
            char szBuffer[4096];
            ssize_t  nRecv 
    = 0;
            nRecv  
    =  this->peer().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;
        }

    };

    typedef  ACE_Acceptor
    <CClientSocketHandler2, ACE_SOCK_Acceptor>  CClientSocketAccept2;

    //使用示例
        
    //监听9981端口,循环处理客户端连接
        ACE_INET_Addr  addr( 9981 );  //监听9981端口

        ACE_Reactor
    * pReactor =  ACE_Reactor::instance();

        CClientSocketAccept2  acceptor;

        
    if( acceptor.open( addr, pReactor ) == -1)
        {
            
    return -1;
        }

        pReactor
    ->run_reactor_event_loop();
    Connector模型同理,略过不提.下面简略地介绍下ACE_Acceptor处理的过程.其接收到客户端连接后,调用handle_input成员方法, handle_input流程如下:
    1.调用make_svc_handler成员方法创建连接处理对象,即此例中的CClientSocketHandler2的实例
    2.调用accept_svc_handler成员方法进行接收操作
    3.调用activate_svc_handler成员方法,其调用CClientSocketHandler2的open方法,完成服务处理器的初始化
  • 相关阅读:
    JavaScript -基础- 变量、常量
    Python 执行SQL带参数
    Python 装饰器
    Bootstrap
    python 数据如何保存到excel中--xlwt
    django 中下载文件与下载保存为excel
    AttributeError: 'cx_Oracle.Cursor' object has no attribute 'numbersAsStrings'
    Python Django 之 基于JQUERY的AJAX 登录页面
    Python Django 之 登录页面
    Python pycharm 引入需要使用的包
  • 原文地址:https://www.cnblogs.com/fangkm/p/1533949.html
Copyright © 2020-2023  润新知