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

TAO教程之九:TAO的COS事件服务

阅读更多
TAO的COS事件服务

不断地找回股票的价格而仅仅是为了检查其价格是否发生了改变这样做并不是有效和可伸缩的方案。当股价改变时我们就可以得到通知的话那么我们就可以执行恰当的动作。尽管我们可以自己设计回调机制,但解决这样的问题使用CORBA事件服务就可以轻松搞定。

定义事件类型

我们需要定义一个IDL结构体来承载我们的事件数据。自然而然,我们需要在事件中包括股票的价格,符号和全称。

  struct Event {
    double price;
    string symbol;
    string full_name;
  };

我们也可以对Stock接口作一些扩展,这样修改股票的价格:

  interface Modify_Stock : Stock {
    void set_price (in double new_price);
  };
获取股价的变化
作消费建立连接

作为消费者建立连接是个相似的过程,但是我们将使用更为传统的基于继承的方法代替TIE。先让我们定义消费者对象:

class Stock_Consumer : public POA_CosEventComm::PushConsumer {
public:
  Stock_Consumer ();

  void push (const CORBA::Any& data);
  void disconnect_push_consumer void);

  // details omitted
};


当事件服务断开时,它将调用disconnect_push_consumer()方法,比如,因为它被关闭前,消费者可以获得一个时机来断开连接。 无论什么时候提供者发出某个事件,事件服务都会调用push()方法。让我们查看一下这个方法,我们先得从任意类型 (any)中抽取事件数据:

void
Stock_Consumer::push (const CORBA::Any& data)
{
  Quoter::Event *event;
  if ((data >>= event) == 0)
    return; // Invalid event

注意,这个抽取操作可能失败:任意对象(any)可以存储所有的IDL数据类型,并且仅在抽取时才检查数据类型。同时再注意我们使用指向事件的指针,CORBA规则是不定长的结构,也就是说,结构体包含不宽长的元素,比如字符串,通过引用被抽取出来。我们不需要管理这个内存,ORB将为我们消费它。现在我们可以把新的股票价格打印出来:

  std::cout full_name.in ()
            symbol.in ()
            price 

回顾我们的示例,当事件通道断开时我们也会接收到回调。在这一点上我们需要忘掉原始的连接:

void
Stock_Consumer::disconnect_push_consumer void)
{
  this->supplier_proxy_ = CosEventChannelAdmin::ProxyPushSupplier::_nil ();
}


但是为什么在最先的地方我们需要有一个与事件通道的连接?我们所需要的所有就是接收事件。与事件通道的连日接将使你能友好的关闭连接,于是事件通道不必为旧的消费者维护资源。例如,我们可以实现的方法如下:

void
Stock_Consumer::disconnect ()
{
  // Do not receive any more events...
  this->supplier_proxy_->disconnect_push_supplier ();
}
怎样连接到事件通道

连接到事件通道分三个步骤:第一步我们获取被所有想要连接的消费者使用的工厂。第二步我们获取提供者代理,于是当不需要任何更多事件的时候我们可以作出报告。最后一上我们连接到代理并开始接收事件。

我们假定我们使用了命名服务或与之类似的服务可以儿取引用给事件服务:

    CORBA::Object_var tmp = naming_context->resolve (name);
    CosEventChannelAdmin::EventChannel_var event_channel =
      CosEventChannelAdmin::EventChannel::_narrow (tmp);


现在我们使用事件通道来获取为消费者连接使用的工厂:

    CosEventChannelAdmin::ConsumerAdmin_var consumer_admin =
      event_channel->for_consumers ();

并命名用工厂获取代理:

void
Stock_Consumer::connect (CosEventChannelAdmin::ConsumerAdmin_ptr consumer_admin)
{
    this->supplier_proxy_ =
      consumer_admin->obtain_push_supplier ();

And finally we connect:

    CosEventComm::PushConsumer_var myself = this->_this ();
    this->supplier_proxy_->connect_push_consumer (myself.in ());
}
通告股价的变化

现在我们将要检查提供者如何生成事件的。让我们查看Modify_Stock接口的实现:

class Quoter_Modify_Stock_i : public POA_Quoter::Modify_Stock {
public:
  Quoter_Modify_Stock_i (const char *symbol,
                         const char *full_name,
                         CORBA::Double price);

  void set_price (CORBA::Double new_price);

private:
  Quoter::Event data_;

  CosEventChannelAdmin::ProxyPushConsumer_var consumer_proxy_;
};

注意我们是如何用IDL结构来维护数据的。这仅是使代码更小更短。 consumer_proxy_ 对象正像上面讨论的supplier_proxy_ 对象,除了我们也用它来发送事件。set_price()方法的开始像下面这样:

void
Quoter_Stock_i::set_price (CORBA::Double new_price)
{
   this->data_.price = new_price;

接下来我们准备事件。COS事件服务使用CORBA的any来发送所有的数据,如下:

   CORBA::Any event;
   event data_;

最后我们向消费者发送事件:

  this->consumer_proxy_->push (event);
}
作为提供者连接到事件服务

发送事件已很容易。作为提供者连到事件通道与作为消费者连接非常相似。我们将需要CosEventComm::PushSupplier 对象。这是一个TIE对象的好的应用程序:

class Quoter_Stock_i : public POA_Quoter::Modify_Stock {
public:
  // some details removed...

  void disconnect_push_supplier (void);

private:
  POA_CosEventComm::PushSupplier_tie  supplier_personality_;
};

PushSupplier_tie是由IDL编译器生成的模板。它实现了CosEventComm::PushSupplier 接口,但它实际上仅仅是转发所有的连接到它的单一模板参数。例如,在这个情况下disconnect_push_supplier 调用实现如下:

template void
POA_CosEventComm::PushSupplier_tie ::disconnect_push_supplier ()
{
  this->ptr_->disconnect_push_supplier ();
}

ptr_成员变量实际上是指向模板参数的指针,因此我们不必实现一个单独的类仅用于接收断开连接的回调,我们可以使用相同的Modify_Stock_i类来处理它。

回过一建立连接的代码,首先我们获得对事件服务的访问,比如使用命名服务:

    CORBA::Object_var tmp = naming_context->resolve (name);
    CosEventChannelAdmin::EventChannel_var event_channel =
      CosEventChannelAdmin::EventChannel::_narrow (tmp);

现在我们用事件通道获取被提供者连接使用的工厂:

    CosEventChannelAdmin::SupplierAdmin_var supplier_admin =
      event_channel->for_suppliers ();

并且命名用这个工厂获得代理:

    this->consumer_proxy_ =
      supplier_admin->obtain_push_consumer ();

然后我们使用提供者个性化地与消费者代理建立连接:

    CosEventComm::PushSupplier_var supplier =
      this->supplier_personality_._this ();
    this->consumer_proxy_->connect_push_supplier (supplier);

最后我们实现断开连接的回调:

void
Quoter_Stock_i::disconnect_push_supplier (void)
{
  // Forget about the consumer.  It is not there anymore
  this->consumer_proxy_ =
    CosEventChannelAdmin::ProxyPushConsumer::_nil ();
}
练习 1

实现接收股价更新事件的消费者。

已提供了头文件 header file , 一起的还有client.cpp. 还提供了这些文件Quoter.idl, Makefile, Stock_i.h, Stock_i.cpp, Stock_Factory_i.h, Stock_Factory_i.cpp, 和server.cpp.

解决方案

用您的方案与Stock_Consumer.cpp比较。

测试

要测试您的变化您需要运行四个程序,先要运行TAO的命名服务:

$ $TAO_ROOT/orbsvcs/Naming_Service/Naming_Service -m 1

接下来是CORBA 事件服务

$ $TAO_ROOT/orbsvcs/CosEvent_Service/CosEvent_Service

再然后运行您的客户端

$ client

最后运行服务端

$ server AAAA MSFT RHAT 

这是 stock_list.txt file.

练习 2

向上面那样配置,但是这次运行多个客户端和服务端:
$ client
$ client
$ server AAAA BBBB $ server ZZZZ YYYY

客户端从两个服务端都接收所有的事件吗?如果您不想接收所有的事件将怎么样?举例来说,因为您只对特定的某些股票感兴趣。

这是stock_list1.txtstock_list2.txt 文件。

不用多播的方式启动命令服务和事件服务的方式:

start %TAO_ROOT%/orbsvcs/Naming_Service/Naming_Service -ORBEndpoint iiop://localhost:2809

start %TAO_ROOT%/orbsvcs/CosEvent_Service/CosEvent_Service -ORBInitRef NameService=corbaloc::localhost:2809/NameService

启动客户端的方式

start client -ORBInitRef NameService=corbaloc::localhost:2809/NameService

启动服务端的方式

start server AAAA BBBB

分享到:
评论

相关推荐

    matlab教程第6章.docx

    `int(A*exp(-i*w*t),t,-tao/2,tao/2)`计算了矩阵`A`乘以指数函数的积分,然后`Yf=simple(yf)`将其化简,结果为与频率`w`相关的表达式。 6.1-6 部分讨论了不同数据类型。`Mn`, `Mc` 和 `Ms` 分别代表了数值矩阵、...

    窄带波束形成.txt

    - `tao2=(k.*cos(theta1(i)*pi/180))/(2*fc);`:对于当前角度`theta1(i)`,计算每个传感器相对于第一个传感器的时间延迟。 - `g=exp(-j*2*pi*fc*tao2.');`:计算针对当前角度的复数权值。 - `abs1(i)=abs(sum(Wc.*g)...

    用MATLAB画齿轮,只要给出基圆半径,齿数就行

    plot([r * cos(tao), R * cos(afa)], [r * sin(tao), R * sin(afa)]); plot([r * cos(q), R * cos(beta)], [r * sin(q), R * sin(beta)]); plot([R * cos(afa), R * cos(beta)], [R * sin(afa), R * sin(beta)]);...

    ibc:Cosmos 网络和链间生态系统的链间标准 (ICS)

    它应用于整合 IBC 的设计原理、协议语义和编码描述,包括核心传输、认证和排序层 (IBC/TAO) 和描述数据包编码和处理语义的应用层 (IBC/APP)。 欢迎投稿。 标准化 请参阅以了解标准所包含的内容。 要提出新标准,...

    MUSIC算法测角的Matlab仿真

    - 使用公式`exp(-2*pi*j*l/lma*[0:6]*cos(q))`来计算每个角度对应的阵列响应向量。 4. **信号传播时间计算**:根据信号源到传感器的距离和光速计算信号传播时间。 - `tao2`, `tao3`, `tao4`分别代表信号从不同...

    信号与系统上机实验-第二次 matlab实现.doc

    x(t) = a0 + ∑[an*cos(2πnt/T) + bn*sin(2πnt/T)] 其中,a0 是直流项,an 和 bn 是谐波分量的系数,T 是信号的周期,n 是谐波的次序。 实验实现 在这个实验中,我们使用 MATLAB 实现了傅立叶级数的计算。我们...

    Matlab积分函数

    Matlab积分函数 Matlab中积分函数是指通过数学运算符号和数值方法来计算定积分的...使用符号积分函数`int(y,t,0,tao)`可以计算积分函数,结果为`s=subs(int(y,t,0,tao),tao,t)。使用`ezplot`函数可以绘制积分图形。

    机器人MATLAB仿真

    yerror=rangeerror^2*sin(Zmeasure(1,i))^2+Zmeasure(2,i)^2*azimutherror^2*cos(Zmeasure(1,i))^2; xyerror=(rangeerror^2-Zmeasure(2,i)^2*azimutherror^2)*sin(Zmeasure(1,i))*cos(Zmeasure(1,i)); P=[xerror x...

    ggplot2:数据分析与图形艺术

    所有译者均来自于统计之都(http://cos.name )。, 爱荷华州立大学的殷腾飞博士、中国人民大学统计学院的孟生旺教授、浙江大学的张政同学通读了译稿,提出了很多有用的建议,殷腾飞博士还提供了大多数新版本中的解决...

    Matlab积分函数.pdf

    >> s=subs(int(y,t,0,tao),tao,t); 可以绘制积分图形: >> subplot(2,1,1) >> ezplot(y,[0,4*pi]),ylim([-0.2,0.7]) >> grid on >> subplot(2,1,2) >> ezplot(s,[0,4*pi]) >> grid on >> title('s=inty(t)dt') ...

    Signal.rar_故障 仿真_故障仿真_轴承仿真_轴承故障仿真_轴承故障信号

    MATLAB提供了多种信号生成函数,如`sin`, `cos`, `randn`等,可以用来构造这些信号。 3. **信号添加**:在正常信号上添加故障特征是故障仿真的关键步骤。这可以通过在信号中引入特定频率或幅度的变化来实现,这些...

    基于MATLAB的DCT域图像水印的研究

    自从1993年起,数字水印技术引起了全球工业界、学术界及军事部门的高度关注,并迅速成为国际研究的热点领域之一。 数字水印技术可以根据其结构层次分为三个主要的研究领域:基础理论研究、应用基础研究以及应用技术...

    信号与系统课设报告

    基于公式`n=4*A*(sin(n*pi/2))^2/((n+tao)^2*pi^2); X=X+fn*cos(n*w0*t); X=X+A/2;`,学生需分析周期三角波的傅立叶级数系数,构建三角波的正弦信号线性组合。通过改变谐波次数,观察吉伯斯现象,这是一种在离散...

    机器人实验报告.pdf

    另外,文档中出现了一些符号变换和简化过程,如 sin、cos 后的参数中带有 (2^0.5),这可能是将角度表示为弧度,以及三角函数展开后参数的简化表示。 文档的最后一部分描述了机器人各个关节的旋转矩阵 T10、T21、T32...

    C语言库函数速查,超方便

    3. 数学运算:库提供了大量的数学函数,例如sin、cos、tan用于三角函数计算,sqrt用于平方根求解,pow用于幂运算,exp用于指数函数,等等。 4. 内存管理:库中的malloc和free函数用于动态分配和释放内存,calloc...

    全自动3D打印的无刷Nerf Blaster Arduino控制-项目开发

    该项目的核心是创建一个全自动3D打印的Nerf Blaster,它受到《赛博朋克2077》游戏中的武器启发,特别是“陶涛枪”。这个创新的玩具枪使用了Arduino控制器,使得射击过程更加智能化和自动化。下面将详细讨论其中涉及...

Global site tag (gtag.js) - Google Analytics