`
pleasetojava
  • 浏览: 705425 次
  • 性别: Icon_minigender_2
  • 来自: 上海
文章分类
社区版块
存档分类
最新评论

CORBA Programming with TAO - 8.Event Service(事件服务)

阅读更多
CORBA Programming with TAO - 8.Event Service(事件服务)
摘要:
事件服务(Event Service)通过在通信的双方甚至是多方间引入一个第三方――Event Channel,一定程度上解除Client和Server之间的耦合关系,在通信的过程中,任意一方只需与Event Channel打交道,而无需确切知道对方的存在,从而使得二者由一对一的关系变成多对多的关系。
一、简介
CORBA除了前面讲过的基本的Naming Service(命名服务)外,还定义了许多其它服务,Event Service就是其中的一个。标准的CORBA通信模式中,Client与Server之间的通信是直接的,Client向Server发出调用请求,Server进行处理并返回结果,这种处理方式下,二者之间是完全耦合在一起的一对一的关系。而Event Service则通过在二者之间引入一个第三方--Event Channel,可在一定程度上解除Client和Server之间的耦合关系,在通信的过程中,任意一方只需与Event Channel打交道,而无需确切知道对方的存在,从而使得二者由一对一的关系变成多对多的关系。
CORBA的Event Service定义了两种通信模式,推模式(Push Model)与拉模式(Pull Model)。在推模式下,PushSupplier向Event Channel发送消息,由Event Channel向Cusumer转发消息;在拉模式下,PullConsumer向Event Channel请求消息,由Event Channel向Supplier转发该请求。但是,并不是说PushSupplier只能与PushConsumer通信,PullSupplier只能与PullConsumer通信,由于Event Channel提供的代理同时也扮演着Supplier/Consumer的角色,因此,在实际应用中,我们可以混合使用两种模式,后面的实例将演示PullSupplier与PushConsumer通过Event Channel连接的例子,这种情况下,代理一方面不断地主动从Supplier处请求消息(默认时间间隔1秒),另一方面,又主动将收到的消息向Consumer发送。
二、编译
与Naming Service一样,Event Service也是TAO的一个独立的Service,其源代码可以在$TAO/orbsvcs/CosEvent_Service下找到,但是前面介绍的CIAO_TAO.mwc产生的工程文件仅包含了TAO的少数几个Service,因此,要编译Event Service需要通过在$TAO_ROOT目录下运行:
mwc.pl -type vc8 TAO.mwc
以产生包含所有TAO实现的Service的工程文件。在执行上述命令前,最好将TAO.mwc的内容改为:
// TAO.mwc,v 1.2 2003/08/22 15:23:48 dhinton Exp
workspace {
exclude {
CIAO
examples
performance-tests
tests
orbsvcs/tests
orbsvcs/performance-tests
orbsvcs/examples
}
}
否则,过多的测试工程将使得上述命令需要很长的时间才能执行完毕。
三、实例
下面举一个PullSupplier的例子,PullSupplier必须从POA_CosEventComm::PullSupplier派生,并实现该接口定义的三个基本方法:
CORBA::Any *pull();
CORBA::Any *try_pull(CORBA::Boolean &has_event);
void disconnect_pull_supplier ();
PullSupplier周期性会收到来自ProxyPullConsumer的pull请求,要求从PullSupplier取得消息。下面是该实例的相关代码:
// Notes: just for demo, no exception handle
#include <orbsvcs/CosEventCommS.h>
#include <orbsvcs/CosEventChannelAdminC.h>
#include <orbsvcs/CosNamingC.h>
#include <process.h>
#include <stdio.h>
#include <iostream>
using namespace std;
class Supplier_i : virtual public POA_CosEventComm::PullSupplier {
public:
Supplier_i () : l(0) {};
// each PullSupplier must implement the following three methods.
CORBA::Any *pull();
CORBA::Any *try_pull(CORBA::Boolean &has_event);
void disconnect_pull_supplier ();
private:
CORBA::ULong l;
};
void Supplier_i::disconnect_pull_supplier () {
cout << "Pull Supplier: disconnected by channel." << endl;
}
CORBA::Any* Supplier_i::pull() {
cout << "Pull Supplier: pull() called. Data : ";
CORBA::Any *any = new CORBA::Any();
*any <<= l++;
cout << l-1 << endl;
return (any);
}
CORBA::Any *
Supplier_i::try_pull(CORBA::Boolean &has_event)
{
cout << "Pull Supplier: try_pull() called. Data : ";
CORBA::Any *any = new CORBA::Any();
*any <<= l++;
cout << l-1 << endl;
has_event = 1;
return (any);
}
int
main(int argc, char **argv)
{
const char* channelName = "CosEventService";
CORBA::Object_var obj;
// Start orb.
CORBA::ORB_ptr orb = CORBA::ORB_init(argc,argv);
// find RootPOA
obj=orb->resolve_initial_references("RootPOA");
PortableServer::POA_var rootPoa = PortableServer::POA::_narrow(obj);
// find and activate POAManager
PortableServer::POAManager_var pman =rootPoa->the_POAManager();
pman->activate();
// find NameService
obj = orb->resolve_initial_references("NameService");
CosNaming::NamingContextExt_var ncRef = CosNaming::NamingContextExt::_narrow(obj);
cout << "Find NameService" << endl;
// search for EventChannel though NameService
CosNaming::Name_var name = ncRef->to_name(channelName);
obj = ncRef->resolve(name);
CosEventChannelAdmin::EventChannel_var channel =
CosEventChannelAdmin::EventChannel::_narrow(obj);
cout << "Find EventChannel" << endl;
// find SupplierAdmin on this channel
CosEventChannelAdmin::SupplierAdmin_var supplier_admin;
supplier_admin = channel->for_suppliers ();
cout << "Find SupplierAdmin" << endl;
// find ProxyPullConsumer under this SupplierAdmin
CosEventChannelAdmin::ProxyPullConsumer_var proxy_consumer;
proxy_consumer = supplier_admin->obtain_pull_consumer ();
// create PullSupplier
Supplier_i* supplier = new Supplier_i ();
CosEventComm::PullSupplier_var supplierRef = supplier->_this();
// Connect PullSupplier with ProxyPullConsumer
proxy_consumer->connect_pull_supplier(supplierRef.in());
cout << "Connect Pull Supplier." << endl;
orb->run();
// cut off connection with ProxyPullConsumer
proxy_consumer->disconnect_pull_consumer();
cout << "Disconnect ProxyPullConsumer." << endl;
// Destroy the POA, waiting until the destruction terminates
rootPoa->destroy (1, 1);
orb->destroy ();
return 0;
}
从上面的代码可以看出,PullSupplier的基本调用序列为:
1、初始化ORB、查找rootPOA并激活POA Manager、查找Name Service并通过Name Service与事件通道取得联系;(这一步与前面讲的Name Service的例子并无差异)
2、在找到对应的事件通道后,PullSupplier通过channel->for_suppliers()找到对应的SupplierAdmin,进而通过SupplierAdmin找到ProxyPullConsumer,这样我们就可以向该代理注册我们的PullSupplier了。
3、最后,我们可以通过调用disconnect_pull_consumer()方法断开与ProxyPullConsumer的连接。
本文附带的源码包还包括了PullConsumer、PushSupplier、PushConsumer等三个例子,基本流程与上面类似,大家可以自行进行比较,以充分掌握各模式对调用序列的影响。
实际上,除了上面将事件数据写入Any类型进行传输外,CORBA规范还定义了一套强类型API,以用于用户自定义类型的传输,%TAO_ROOT%/orbsvcs/examples/CosEC/TypedSimple是一个强类型EventChannel的例子。
四、运行
由于上述实例需要同时使用Naming_Service、Event_Service,因此,需要在启动程序前先启动这两个服务:
%TAO_ROOT%/orbsvcs/Naming_Service/Naming_Service -m 1
%TAO_ROOT%/orbsvcs/CosEvent_Service/CosEvent_Service
然后即可启动客户程序:
pushcons
pushsupp
五、小结
Event Service为Supplier与Consumer提供了一种基本的借助第三方进行通信的机制,从而一定程度上解除了二者之间的耦合关系,但由于Event Service没有提供Filter机制,所有事件在整个事件通道内进行广播,使得Consumer无法订阅自己感兴趣的事件,同时,对QoS的等方面的支持也十分有限,因此,对于我们的实际应用,Event Service往往只能被应用于十分简单的松散耦合的多方通信。
CORBA规范定义的Notification Service从很大程度对Event Service进行了扩展,避免了Event Service存在的一些问题,感兴趣的朋友可以访问:
来获得在TAO中使用Notification Service的相关信息。
参考:
1. Alex Tingle, Paul Nader. omniEvents. http://omnievents.sourceforge.net/doc/index.html
5. Chris Gill, Tim Harrison, and Carlos O'Ryan. Using the Real-Time Event Service. http://www.cs.wustl.edu/~schmidt/events_tutorial.html
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics