[dotNET]WSE2.0中的发送器/接收器流程用于WebService与后台侦听服务交互

<iframe align="center" marginwidth="0" marginheight="0" src="http://www.zealware.com/csdnblog336280.html" frameborder="0" width="336" scrolling="no" height="280"></iframe>

WSE2.0中的发送器/接收器交互流程

编写者

版本

郑昀@神州泰岳

0. 1

摘要:本章节简单介绍了如何让Web Service通过COM+服务器组件和后台的SoapReceiver/SoapSender作交互,我们还介绍了WSE2.0中的发送器/接收器设计概念,并给出交互流程的详细描述。

COM+服务器组件和后台的SoapReceiver/SoapSender作交互,我们还介绍了WSE2.0中的发送器 / 接收器设计概念,并给出交互流程的详细描述。

首先简单介绍WSE 2.0中的消息处理:

Web Services Enhancements 2.0允许用户开始体验除 HTTP 以外的其他 XML 消息处理可能性。WSE 2.0 .NET 框架的一个附件。

WSE2.0提供了一种增强的消息处理 API,它支持其他传输和自定义消息交换模式 (MEP)

发送器与接收器

“一旦离开传统的 RPC 模型,您必须停止以客户端与服务器的方式思考问题。

当开始使用非传统的 MEP 时,这些术语经常使人困惑不解。相反,把 Web 服务结构中的不同实体当作 SOAP 发送器与接收器更为恰当。一些节点旨在发送 SOAP 消息,而其他一些节点旨在接收和处理这些消息。并且这些角色是完全可互换的,即一个给定的节点可以有时作为发送器,有时则作为接收器。

WSE 2.0 通过为发送和接收 SOAP 消息提供两个基本的类来强调这种思考方式:SoapSender SoapReceiver。顾名思义,SoapSender 将发送 SOAP 消息的过程封装到一个 URI,而 SoapReceiver 将接收 SOAP 消息的过程封装在一个特定的 URI 中。

WSE 2.0 使用三个通讯协议支持发送和接收消息:进程内、TCP HTTP。在进程内情况下,SOAP 消息被直接发送到接收器,而不用通过网络层。用户需要指出通过 URI 想要使用哪种机制(SoapSender SoapReceiver),该机制必须遵循以下 WSE 2.0 中的语法:

protocol_scheme://host[:port_number]/path_info/...

协议方案指出使用哪种协议,而主机和端口号标识在哪里发送消息。路径信息标识在特定主机上访问哪种资源。

.NET 框架为在用户代码中表示 URI 提供了 System.Uri 类。用户可以通过向构造函数提供适当的 URI 字符串来实例化 Uri 对象,如下所示:

Uri myuri = new Uri("soap.tcp://mymachine/math");

SoapSender SoapReceiver 需要用户提供 Uri 对象以指出使用的协议和终结点详细信息。

除了支持新的传输,WSE 2.0 消息处理 API 与现有 WebMethod 框架的另一重大区别在于:SoapSender SoapReceiver 需要开发人员直接使用 SOAP 消息。尽管它提高了 XML SOAP 所需开发经验的门槛,但是它也提高了灵活性并更加关注于 XML 消息处理。

WSE 2.0 为构建和处理用户代码中的 SOAP 消息提供了Microsoft.Web.Services.SoapEnvelope 类。SoapEnvelope 类从 System.Xml.XmlDocument 中派生,并且提供了只应用于 SOAP 消息(如 EnvelopeHeader Body 属性)的额外成员。”原话出自Aaron Skonnard。

WSE2.0的路由中立寻址和消息处理

“WSE 2.0 WS-Addressing 下一个跃点路由提供了完整的支持。我们在WSE2.0的基础之上,构建消息交互,就容易多了。

下面我们列出常用的一些信息头:

名称

类型

说明

wsa:MessageID

xsd:anyURI

用于在时间和空间上唯一标识该消息的 URI

wsa:To

xsd:anyURI

该消息的预期接收方的地址。

wsa:Action

xsd:anyURI

标识符,用于唯一地(和不透明地)标识该消息所暗示的语义。

wsa:From

endpoint-ref

对作为消息来源的终结点的引用。

wsa:ReplyTo

endpoint-ref

终结点引用,标识答复该消息的预期接收方。如果期望得到答复,则消息必须包含 wsa:ReplyTo 标头。发送方必须使用 wsa:ReplyTo 标头的内容来表示答复消息。如果没有 wsa:ReplyTo 标头,则可能使用 wsa:From 标头的内容来编制到来源的消息。如果消息无有意义的答复,则可能不存在该属性。如果有该属性,则 wsa:MessageID 标头是 REQUIRED

1. WS-Addressing 消息的常用信息头

我们可以使用 <to></to> 指定消息的目标,使用 <action></action> 指定操作,并使用 <messageid></messageid> 为消息指定唯一的 ID,使用 <replyto></replyto> 指定消息的回复应该发送给哪一个终结点。”原话出自Aaron Skonnard

Web Service—COM+服务器组件—后台侦听服务的订阅关系

由于Web Service运行的身份是ASP.NET用户,而SoapReceiver.Add方法对执行权限要求较高,所以我们把WS_Messaging这部分搬到COM+组件中,并把它配置为在专门的服务器进程中激活,通过这种方式提升权限。

首先Web Service调用COM+服务器组件的接口方法。

其次,COM+服务器组件中,我们定义了SubscriberNotification类,从 SoapReceiver 中派生一个新类并重载它的 Receive 方法(它获取一个 SoapEnvelope 参数),可以实现 SoapReceiver

public class SubscriberNotification : SoapReceiver

{

protected override void Receive(Microsoft.Web.Services2.SoapEnvelope envelope)

{

// implement Receive here

}

}

Receive中,我们根据envelope.Context.Addressing.Action的消息语义,处理传入的 SOAP 消息并执行请求的操作,这里我们定义了两种语义:

Response:表明是服务器/发布者对订阅请求的响应;

Notify:表明是服务器/发布者发布了一个消息。

我们利用SubscriberNotification类实例,通过调用:

SubscriberNotification client = new SubscriberNotification();

Uri clientUri = new Uri ( Literals.LocalhostTCP + "8082/Client" );

SoapReceivers.Add ( clientUri, client );

来注册一个带有特定的Uri“soap:tcp://server.8082/ClientSoapReceiver对象。

一旦配置了接收器,将来如果有消息到达特定的终结点时,这个接收器的Receive 方法将被调用。

然后,实例化一个 SoapSender 对象并把它绑定到目标 URI 中:

string sPublisherUri = "soap.tcp://server:port/Publisher";

Uri recipientUri = new Uri (sPublisherUri);

SoapSender registrationSender = new SoapSender ( recipientUri );

并且通过 SoapEnvelope.Context.Action 属性指定消息操作

SoapEnvelope message = new SoapEnvelope ();

message.Context.Addressing.Action = new Action ( "subscribe" );

最后,通过

registrationSender.Send ( message );

发送单向消息。这个消息一方面用于通知订阅关系,另一方面传递了手机号码等各项参数。

服务器/发布者的反向消息可以通过前面定义的SoapReceiverCOM+服务器组件接收到。

正在监听的后台侦听服务收到了消息,进行处理:

添加这个订阅者;

通知订阅者订阅流水号;

请求其他服务,得到请求的信息后把该信息用SoapSender通知订阅者。

最后,订阅者COM+服务器组件收到通知后,不再阻塞,将参数输出给Web Service

流程图如下图所示:

<shapetype id="_x0000_t75" coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f"></shapetype><stroke joinstyle="miter"></stroke><formulas></formulas><f eqn="if lineDrawn pixelLineWidth 0"></f><f eqn="sum @0 1 0"></f><f eqn="sum 0 0 @1"></f><f eqn="prod @2 1 2"></f><f eqn="prod @3 21600 pixelWidth"></f><f eqn="prod @3 21600 pixelHeight"></f><f eqn="sum @0 0 1"></f><f eqn="prod @6 1 2"></f><f eqn="prod @7 21600 pixelWidth"></f><f eqn="sum @8 21600 0"></f><f eqn="prod @7 21600 pixelHeight"></f><f eqn="sum @10 21600 0"></f><lock v:ext="edit" aspectratio="t"></lock><shape id="_x0000_i1025" style="WIDTH: 476.25pt; HEIGHT: 537pt" type="#_x0000_t75" o:ole="" o:bordertopcolor="this" o:borderleftcolor="this" o:borderbottomcolor="this" o:borderrightcolor="this"></shape><imagedata src="file:///C:%5CDOCUME~1%5CVICTOR~1%5CLOCALS~1%5CTemp%5Cmsohtml1%5C01%5Cclip_image001.emz" o:title=""></imagedata><bordertop type="single" width="18" shadow="t"></bordertop><borderleft type="single" width="18" shadow="t"></borderleft><borderbottom type="single" width="18" shadow="t"></borderbottom><borderright type="single" width="18" shadow="t"></borderright>

3-1 流程逻辑

专用的Delegate事件类{EventHandlerClass}

之所以把delegate的函数专拎出来作为一个类,是因为如果这两个函数放在RequestRoute类中,那么通过

client.ResponseFromServerEvent += new ResponseFromServerEventHandler(this.ListenForResponse);

来添加delegate,当发布事件时,ListenForResponse是无法收到的,但在一个控制台程序中这么做是可以的。

除非另外作出一个类,并且

EventHandlerClass handler = new EventHandlerClass();

handler.me = this;

client.ResponseFromServerEvent +=

new ResponseFromServerEventHandler(handler.ListenForResponse);

这样,才可以。

ListenForNotification:

当从服务器/发布者通知的消息的envelope.Context.Addressing.Action的消息语义是“notification”时,我们通过SubscriberNotification类的Receive函数中调用

OnResponseFromServer(sResponse);

发布这个消息,从而调用了EventHandlerClass类的ListenForNotification委托函数。

我们在这个委托函数中做到了以下两点:

1.设置ReuqestRoute对象的PublishData属性为收到的消息,这样就顺利地将Publisher(远端发布者,可能是一个服务或者一个Webservice)的发布信息记录下来了;

2.设置ReuqestRoute对象的m_manRE为有信号,这样本组件的接口函数就可以顺利返回,不再被阻塞;

ListenForResponse:

当从服务器/发布者通知的消息的envelope.Context.Addressing.Action的消息语义是“response”时,我们通过SubscriberNotification类的Receive函数中调用

OnSubscriptionNotification (sResponse);

发布这个消息,从而调用了EventHandlerClass类的ListenForResponse委托函数。

我们在这个委托函数中主要是想:

从发布者返回的包里面找到订阅ID,并保存到主对象中。

郑昀@UltraPower编辑。

Disclaimers

本文档仅供参考。本文档所包含的信息代表了在发布之日,zhengyun_ustc对所讨论问题的当前看法,zhengyun_ustc不保证所给信息在发布之日以后的准确性。

用户应清楚本文档的准确性及其使用可能带来的全部风险。可以复制和传播本文档,但须遵守以下条款:

  1. 复制时不得修改原文,复制内容须包含所有页

  2. 所有副本均须含有 zhengyun_ustc的版权声明以及所提供的其它声明

  3. 不得以赢利为目的对本文档进行传播

Disclaimers

本文档仅供参考。本文档所包含的信息代表了在发布之日,zhengyun_ustc对所讨论问题的当前看法,zhengyun_ustc不保证所给信息在发布之日以后的准确性。

用户应清楚本文档的准确性及其使用可能带来的全部风险。可以复制和传播本文档,但须遵守以下条款:

  1. 复制时不得修改原文,复制内容须包含所有页

  2. 所有副本均须含有 zhengyun_ustc的版权声明以及所提供的其它声明

  3. 不得以赢利为目的对本文档进行传播




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值