ACE技术论文集-第9章连接和初始化通信服务的对象创建模式
发布: 2008-6-13 14:37 | 作者: Prashant Jain and D | 来源: 转载 | 查看: 334次
这一部分解释使用接受器-连接器模式来构建通信软件应用所涉及的步骤。这里的实现基于ACE OO网络编程工具包[6]中的可复用组件和应用。ACE提供一组丰富的可复用C++包装和构架组件,它们可在一系列OS平台上执行常用的通信软件任务。
接受器-连接器模式中的参与者被划分为反应、连接和应用层,如图9-6所示。
反应和连接层分别为分派事件和初始化服务执行通用的、与应用无关的策略。应用层通过提供建立连接和执行服务处理的具体类来实例化这些通用策略。这样的事务分离增强了接受器-连接器模式实现中的可复用性、可移植性和可扩展性。

图9-6 Acceptor-Connector模式实现中的参与者的分层和划分
下面对接受器-连接器模式实现的讨论从底部的反应层开始,并向上通过连接层和应用层。
反应层处理发生在由I/O句柄表示的传输端点(比如socket端点)上的事件。该层的两个参与者,Initiation Dispatcher(发起分派器)和Event Handler(事件处理器),是由反应堆(Reactor)模式[3]定义的。该模式使得程序在单线程控制中就能够高效地完成来自多个来源的多种类型的事件的多路分离。
反应层中的两个主要角色是:
事件处理器:它规定由挂钩方法[7]组成的接口,抽象地表示应用可提供的事件处理操作。例如,这些挂钩方法表示这样一些事件:新连接请求、异步开始的连接请求的完成,或是来自相连对端的数据的到达,等等。Acceptor和Connector组件是从Event Handler派生的具体的事件处理器。
发起分派器:为登记、移除和分派Event Handler定义接口。Synchronous Event Demultiplexer(同步的事件多路分离器),比如select[8]或WaitForMultipleObjects[9],通知Initiation Dispatcher何时回调应用特有的事件处理器,以响应特定类型的事件。常用事件包括连接接受事件、数据输入和输出事件,以及超时事件。
注意Initiation Dispatcher是9.6描述的Dispatcher的实现。一般而言,接受器-连接器Dispatcher可以是反应式、前摄式(Proactive)或多线程的。在这一实现中的特定的Initiation Dispatcher使用反应式模型来在单线程控制中多路分离和分派具体的事件处理器。在我们的例子中,Initiation Dispatcher是单体(Singleton)[10],因为我们只需要它的一个实例用于整个进程。
连接层:
- 创建Service Handler;
- 被动地或主动地将Service Handler连接到它们的远地对端;以及
- 一旦连接,启用Service Handler。
在此层中的所有行为都是完全通用的。特别地,注意下面描述的实现中的类是怎样委托具体的IPC机制和Concrete Service Handler的;后者是由在9.8.3中描述的应用层实例化的。
应用层委托连接层的方式与连接层委托反应层的方式相类似。例如,反应层中的Initiation Dispatcher代表连接层处理与初始化有关的事件,比如异步的建立连接。
在连接层中有三个主要角色:Service Handler(服务处理器)、Acceptor和Connector。
- 服务处理器:该抽象类继承自Event_Handler,并为客户、服务器或同时扮演两种角色的组件所提供的服务处理提供通用接口。应用必须通过继承来定制此类,以执行特定类型的服务。Service Handler接口如下所示:
// PEER_STREAM is the type of the
// Concrete IPC mechanism.
template
class Service_Handler : public Event_Handler
{
public:
// Pure virtual method (defined by a subclass).
virtual int open (void) = 0;
// Accessor method used by Acceptor and
// Connector to obtain the underlying stream.
PEER_STREAM &peer (void)
{
return peer_stream_;
}
// Return the address that we’re connected to.
PEER_STREAM::PEER_ADDR &remote_addr (void)
{
return peer_stream_.remote_addr ();
}
protected:
// Concrete IPC mechanism instance.
PEER_STREAM peer_stream_;
};
一旦Acceptor或Connector建立了连接,它们调用Service Handler的open挂钩。该纯虚方法必须被Concrete Service Handler子类定义;后者执行服务特有的初始化和后续处理。
连接器:该抽象类实现主动连接建立和初始化Service Handler的通用策略。它的接口如下所示:
// The SERVICE_HANDLER is the type of service.
// The PEER_CONNECTOR is the type of concrete
// IPC active connection mechanism.
template
class PEER_CONNECTOR>
class Connector : public Event_Handler
{
public:
enum Connect_Mode
{
SYNC, // Initiate connection synchronously.
ASYNC // Initiate connection asynchronously.
};
// Initialization method.
Connector (void);
// Actively connecting and activate a service.
int connect (SERVICE_HANDLER *sh,
const PEER_CONNECTOR::PEER_ADDR &addr,
Connect_Mode mode);
protected:
// Defines the active connection strategy.
virtual int connect_service_handler(SERVICE_HANDLER *sh,
const PEER_CONNECTOR::PEER_ADDR &addr,
Connect_Mode mode);
// Register the SERVICE_HANDLER so that it can
// be activated when the connection completes.
int register_handler (SERVICE_HANDLER *sh, Connect_Mode mode);
// Defines the handler’s concurrency strategy.
virtual int activate_service_handler(SERVICE_HANDLER *sh);
// Activate a SERVICE_HANDLER whose
// non-blocking connection completed.
virtual int complete (HANDLE handle);
private:
// IPC mechanism that establishes
// connections actively.
PEER_CONNECTOR connector_;
// Collection that maps HANDLEs
// to SERVICE_HANDLER *s.
Map_Managerhandler_map_;
// Inherited from the Event_Handler -- will be
// called back by Eactor when events complete
// asynchronously.
virtual int handle_event (HANDLE, EVENT_TYPE);
};
// Useful "short-hand" macros used below.
#define SH SERVICE_HANDLER
#define PC PEER_CONNECTOR
Conncetor通过特定类型的PEER CONNECTOR和SERVICE HANDLER被参数化。PEER CONNECTOR提供的传输机制被Connector用于主动地建立连接,或是同步地、或是异步地。SERVICE HANDLER提供的服务对与相连的对端交换的数据进行处理。C++参数化类型被用于使(1)连接建立策略与(2)服务处理器类型、网络编程接口和传输层连接协议去耦合。
参数化类型是有助于提高可移植性的实现决策。例如,它们允许整体地替换Connector所用的IPC机制。这使得Connector的连接建立代码可在含有不同网络编程接口(例如,有socket,但没有TLI;反之亦然)的平台间进行移植。例如,取决于平台是支持socket还是TLI[11],PEER CONNECTOR模板参数可以通过SOCK Connector或TLI Connector来实例化。使用参数化类型的另一个动机是改善运行时效率,因为模板实例化发生在编译时。
更为动态的去耦合可以经由继承和多态、通过使用[10]中描述的工厂方法(Factory Method)和策略(Strategy)模式来完成。例如,Connector可以存储指向PEER CONNECTOR基类的指针。根据从工厂返回的PEER CONNECTOR的子类,这个PEER CONNECTOR的connect方法可在运行时被动态地绑定。一般而言,在参数化类型和动态绑定之间的权衡是参数化类型可能带来额外的编译/链接时开销,而动态绑定可能带来额外的运行时开销。
connect方法是应用用以通过Connector来发起连接的入口。它的实现如下所示:
template int
Connector::connect(SERVICE_HANDLER *service_handler,
const PEER_CONNECTOR::PEER_ADDR &addr,
Connect_Mode mode)
{
connect_service_handler (service_handler, addr, mode);
}
该方法使用桥接(Bridge)模式[10]来使Concrete Connector能透明地修改连接策略,而不用改变组件接口。为此,connect方法委托Connector的连接策略,connect_service_handler,来发起连接。如下所示:
template int
Connector::connect_service_handler
(SERVICE_HANDLER *service_handler,
const PEER_CONNECTOR::PEER_ADDR &remote_addr,
Connect_Mode mode)
{
// Delegate to concrete PEER_CONNECTOR
// to establish the connection.
if (connector_.connect (*service_handler,
remote_addr,
mode) == -1)
{
if (mode == ASYNC && errno == EWOULDBLOCK)
{
// If connection doesn’t complete immediately
// and we are using non-blocking semantics
// then register this object with the
// Initiation_Dispatcher Singleton so it will
// callback when the connection is complete.
Initiation_Dispatcher::instance
()->register_handler (this, WRITE_MASK);
// Store the SERVICE_HANDLER in the map of
// pending connections.
handler_map_.bind
(connector_.get_handle (), service_handler);
}
}
else if (mode == SYNC)
// Activate if we connect synchronously.
activate_service_handler (service_handler);
}
最新更新
- ACE_Reactor中使用register_hand... 6-13
- ACE技术论文集-第1章 ACE自适配... 6-13
- ACE技术论文集-第2章 包装外观 W... 6-13
- ACE技术论文集-第3章 高效可移植... 6-13
- ACE技术论文集-第4章 ACE轻量级O... 6-13
- ACE技术论文集-第5章 C/C++线程... 6-13
- ACE技术论文集-第6章 主动对象(Ac... 6-13
- ACE技术论文集-第7章 ACE反应堆R... 6-13
- ACE技术论文集-第8章 异步事件多... 6-13
- ACE技术论文集-第9章连接和初始... 6-13
