前言: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.\n")); return -1;// ERROR } }; My_Time_Server_Handler::~My_Time_Server_Handler() { ACE_DEBUG((LM_DEBUG,"~My_Time_Server_Handler()\n")); } 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\n"),ACE_TEXT ("connection failed!"))); return -1; } if (sock_stream.close () == -1) //close the connection { ACE_ERROR ((LM_ERROR,ACE_TEXT ("(%P|%t) %p\n"),ACE_TEXT ("sock close"))); return -1; } return 0; }
执行结果:每次执行client都会创建一个服务端的服务处理对象,并随即被释放(我们有益让open方法返回-1来释放服务处理对象,从而来说明整个事件的流程)