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方法,完成服务处理器的初始化
posted @ 2009-07-29 13:04  孤竹君  阅读(809)  评论(0编辑  收藏  举报