[dotNET]WSE2.0中的发送器/接收器流程用于WebService与后台侦听
WSE2.0中的发送器/接收器交互流程
摘要:本章节简单介绍了如何让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 消息(如 Envelope、Header和 Body 属性)的额外成员。”原话出自Aaron Skonnard。 WSE2.0的路由中立寻址和消息处理“WSE 2.0 为 WS-Addressing 和“下一个跃点”路由提供了完整的支持。我们在WSE2.0的基础之上,构建消息交互,就容易多了。 下面我们列出常用的一些信息头:
表 1. WS-Addressing 消息的常用信息头
? ? 我们可以使用
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/Client”的SoapReceiver对象。 一旦配置了接收器,将来如果有消息到达特定的终结点时,这个接收器的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 ); 发送单向消息。这个消息一方面用于通知订阅关系,另一方面传递了手机号码等各项参数。 服务器/发布者的反向消息可以通过前面定义的SoapReceiver被COM+服务器组件接收到。
? ? 正在监听的后台侦听服务收到了消息,进行处理: 添加这个订阅者; 通知订阅者订阅流水号; 请求其他服务,得到请求的信息后把该信息用SoapSender通知订阅者。
? ? 最后,订阅者COM+服务器组件收到通知后,不再阻塞,将参数输出给Web Service。
? ? 流程图如下图所示:
图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不保证所给信息在发布之日以后的准确性。 用户应清楚本文档的准确性及其使用可能带来的全部风险。可以复制和传播本文档,但须遵守以下条款:
Disclaimers:本文档仅供参考。本文档所包含的信息代表了在发布之日,zhengyun_ustc对所讨论问题的当前看法,zhengyun_ustc不保证所给信息在发布之日以后的准确性。 用户应清楚本文档的准确性及其使用可能带来的全部风险。可以复制和传播本文档,但须遵守以下条款:
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=326968 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |