zoukankan      html  css  js  c++  java
  • Acceptor-Connector模式一(Acceptor的工作)V2.0

     前言:ACE Acceptor-Connector模式

    首先这样的模式肯定是面向连接的TCP/IP协议。

    无论是什么场景。差点儿面向连接的通信程序总是由一端主动发起连接,一端监听等待对方的连接。
    这就是接收器-连接器模式(server-client)。

    模式思想

    (1)此模式仅仅负责连接的建立。无论有多少连接上来,这个模式都能应对。
    (2)至于连接建立之后怎样通信,那是通信处理器的事情,与此模式不再有不论什么关系。

    (3)资源的管理总是通过调用函数的返回值来做约定的处理。不用类型假设有特殊的资源管理需求。均能够覆盖父类的方法。

    相关类

    (1)ACE_Svc_Handler  : ACE_Task (服务处理器)连接服务的本地端,成员变量PEER_STREAM peer_由模板參数化。一般为ACE_SOCK_Stream,负责通信的详细运行。ACE_SOCK_Stream既能够读也能够写socket。

    (2)ACE_Acceptor (接受器)该工厂被动的接受连接,并随即初始化一个ACE_Svc_Handler 对象来响应。接收器的handle_input方法截获连接信息,并创建服务处理类,最后运行服务处理类的open方法启动服务处理流程。
    (3)ACE_Connector (连接器)该工厂主动的连接到对端接受器,并随即初始化一个ACE_Svc_Handler 对象来响应
    (4)ACE_Reactor 运行不依赖于应用的一般的消息分发策略

    一、接收器的工作

    接收器的工作流程:
    (1)接收器的open函数会在指定port监听
    (2)将自己与AACE_Event_Handler::ACCEPT_MASK事件一起注冊到反应器
    (3)对端发起连接请求之后,反应器回调ACE_Acceptor ::handle_input方法
    (4)handle_input方法就会创建连接处理器对象。并调用连接处理器的open方法
    (5)handle_input方法返回-1的时候反应器就会回调接收器的handle_close方法,(參考ACE_Reactor的工作逻辑
    (6)接收器的handle_close方法主要工作是关闭注冊事件,并关闭socket资源(运行peer_acceptor_.close())

    二、接收器handle_input的工作

    handle_input的工作主要包含三部分:
    (1)依据模板參数创建服务处理对象new ACE_Svc_Handler
    (2)调用成员ACE_SOCK_Acceptor peer_acceptor_的acceptor方法。指定当连接成功建立之后由服务处理对象ACE_Svc_Handler来处理连接
    (3)调用服务处理对象的open方法
    1)服务处理对象的open方法会注冊ACE_Event_Handler::READ_MASK事件到ACE_Reactor
    2)服务处理对象的open方法会发起receive动作開始读,
    3)服务处理对象的读取完毕会运行handle_input。至于服务处理对象的handle_input方法返回-1则是ACE_Reactor的处理逻辑了。
    (4)服务处理对象的open方法假设返回-1。则调用服务处理对象的close方法(),ACE_Svc_Handler的close方法会调用handle_close。进而调用destroy,进而调用delete this
    template <typename PEER_STREAM, typename SYNCH_TRAITS> int
    ACE_Svc_Handler<PEER_STREAM, SYNCH_TRAITS>::handle_close (ACE_HANDLE,
                                                           ACE_Reactor_Mask)
    {
      ACE_TRACE ("ACE_Svc_Handler<PEER_STREAM, SYNCH_TRAITS>::handle_close");
    
      if (this->reference_counting_policy ().value () ==
          ACE_Event_Handler::Reference_Counting_Policy::DISABLED)
        {
          this->destroy ();
        }
    
      return 0;
    }
    template <typename PEER_STREAM, typename SYNCH_TRAITS> void
    ACE_Svc_Handler<PEER_STREAM, SYNCH_TRAITS>::destroy (void)
    {
      ACE_TRACE ("ACE_Svc_Handler<PEER_STREAM, SYNCH_TRAITS>::destroy");
    
      // Only delete ourselves if we're not owned by a module and have
      // been allocated dynamically.
      if (this->mod_ == 0 && this->dynamic_ && this->closing_ == false)
        // Will call the destructor, which automatically calls <shutdown>.
        // Note that if we are *not* allocated dynamically then the
        // destructor will call <shutdown> automatically when it gets run
        // during cleanup.
        delete this;
    }

    演示样例

    以下的程序会在1500port持续监听,每当有对端发来连接。就创建本地连接处理对象,创建完之后就通过连接处理对象的open返回-1来告诉反应器来释放该对象。

    Acceptor 服务端

    #include <ace/Log_Msg.h>
    #include "ace/Svc_Handler.h"
    #include <ace/Acceptor.h>
    #include "ace/SOCK_Acceptor.h"
    #include "ace/INET_Addr.h"
    #include "ace/Reactor.h"
    
    class My_Time_Server_Handler : public ACE_Svc_Handler<ACE_SOCK_Stream,ACE_NULL_SYNCH>
    {
    public:
    	~My_Time_Server_Handler();
    	//由接收器在接收到对端的连接请求之后调用此方法
    	virtual int open(void *)
    	{
    		ACE_DEBUG((LM_DEBUG,"one client connection established.
    "));
    		return -1;// ERROR
    	}
    };
    
    My_Time_Server_Handler::~My_Time_Server_Handler()
    {
    	ACE_DEBUG((LM_DEBUG,"~My_Time_Server_Handler()
    "));
    }
    
    int main(int argc, char *argv[])
    {
    	ACE_INET_Addr local_addr(1500);
    
    	ACE_Acceptor<My_Time_Server_Handler,ACE_SOCK_Acceptor> acceptor;
    
    	acceptor.open(local_addr,ACE_Reactor::instance());
    	//截过连接信息
    	ACE_Reactor::instance()->run_reactor_event_loop();
    
    	return 0;
    }
    Connector客户端

    #include <ace/Log_Msg.h>
    #include <ace/SOCK_Connector.h>
    #include "ace/INET_Addr.h"
    
    int main(int argc, char *argv[])
    {
    	ACE_INET_Addr addr(1500,"127.0.0.1"); //remote address
    	ACE_SOCK_Connector client_connetor; // connetor for socket client
    	ACE_SOCK_Stream sock_stream; // stream is for socket read/write
    
    	if(client_connetor.connect(sock_stream,addr)==-1) //connect to remote address
    	{
    		ACE_DEBUG ((LM_DEBUG,ACE_TEXT ("(%P|%t) %p
    "),ACE_TEXT ("connection failed!")));
    		return -1;
    	}
    	if (sock_stream.close () == -1) //close the connection
    	{
    		ACE_ERROR ((LM_ERROR,ACE_TEXT ("(%P|%t) %p
    "),ACE_TEXT ("sock close")));
    		return -1;
    	}
    	return 0;
    }
    

    执行结果:每次执行client都会创建一个服务端的服务处理对象,并随即被释放(我们有益让open方法返回-1来释放服务处理对象,从而来说明整个事件的流程)





  • 相关阅读:
    [php]php时间戳当中关于时区的问题
    [jQuery] jQuery如何获取同一个类标签的所有的值
    sed 命令基础
    Docker 学习第6课
    Docker 学习第五课
    Docker 学习第四课
    Docker 学习第三课
    Docker 学习第二课
    Docker学习第一课
    XdeBug的使用
  • 原文地址:https://www.cnblogs.com/mthoutai/p/6800386.html
Copyright © 2011-2022 走看看