好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

消息交换模式 response/reply oneway deplex

消息交换模式 response/reply oneway deplex

wcf基础知识之 查看soap消息 TcpTrace

今天本来准备了wcf的三种消息模式  wcf 基础知识 之 消息交换模式 response/reply oneway deplex   的介绍,但是考虑到里面有说到soap消息,但是可能还有一些朋友对如何查看soap消息还不是很清楚,所以这次先来把如何查看wcf通信的介质--soap消息介绍一下。

其实这个工具的使用非常简单,可以说如果知道了怎么做那是小学一年级的水平,但是我就曾经在这个一年级还浪费了好一些时间,所以为了避免浪费大家的时间,毕竟程序员的时间不是特别多。

TcpTrace 专业查看wcf通信的工具,使用非常简单,但是为了演示如何使用这个小工具,以及我们应该注意哪些地方,还是通过一个简单的例子来描述一下,这样有图有真相。

示例程序还是在原来我们一起做的那个示例项目上进行,因为涉及到的知识点很少,所以我们重点说如何使用工具,而把wcf的部分尽量简洁。

大家请注意我标红的那部分,那个是我们要使用到的服务地址,一个计算的服务地址。这是wcf服务器端的配置,准确的说这次介绍tcpTrace根本不需要这部分的出现,但是为了连贯性,以及可以让大家明白我在做什么,所以我还是把它贴出来了。

客户端的配置才是重点,首先我们定义了客户端终结点,制定了服务的地址,但是有一点我们需要注意,就是在我们添加了终结点行为的配置,并且我们制定了clientVia的值,clientVia是什么意思呢?我们可以理解成一个转发地址。也就是说我们如果制定这个clientVia的地址,那么客户端也会自动转发到真正的服务地址。这就相当于我们可以指定很多不同的clientVia的值,但是他们都是指向的同一个服务地址,这就会造成一个假象,就是我们创建了很多的服务,工作量很大,但是实际上我们就使用到了一个服务。

clientVia的值的设定是关键,这里我们设定它的地址的端口号为8083,而我们实际的服务的地址的端口号为9999.这就是我们在tcpTrace中药设定的两个端口号。

监听端口就是我们在clientVia中设定的端口号,而目标端口号则是实际的服务地址的端口号。当然服务器地址需要我们制定我们服务所在的地址,这里是本机,我们可以指定localhost或127.0.0.1.

tcptrace中的消息就是我们要监听的soap。我本来准备监听的是net.tcp,但是这个工具监听到的结果都是乱码,所以我最后还是改成了wsDualHttobinding的双工通信模式。

 

好了,我这里重点要说的就是客户端配置行为中的clientvia的设定,只要这个设定好了,我们就可以正常监听了。其实对于http的监听,flidder也是可以的,并且我想它的功能可能更强大一些。

赚钱是一种能力,花钱是一种水平,能力可以练,水平是轻易练不出来的。

年轻人不可以太狂。

 

每天进步一点,一年就会进步一大步,十年就可以成功,君子当自强不息,君子当好好学习,每天进步

 

分类:  Wcf

wcf 基础知识 之 消息交换模式 response/reply oneway deplex

 

wcf支持请求-回复(response-reply)、单工(oneway)以及双工(duplex)三种消息交换模式。今天我们来说一下第一种消息交换模式--请求--回复,请注意这里是消息交换模式。

请求-回复消息交换模式是默认的wcf通信方式,如果我们不显式的设定消息交换模式,那么它就是response-reply模式。这和我们通过浏览器访问一个网址的原理是一致的,客户端发起一个请求,然后客户端等待服务器的响应,服务端处理完成返回结果,在客户端显示,如果超时,浏览器会提示无法显示页面的错误。其实原理是一致的,并且如果采用http作为传输协议的话,可以说没有任何的区别。

   1   namespace   Chinaer.WcfDemo.Contracts
   2   {
   3       [ServiceContract()]
   4       public   interface   ICalculator
   5       {
   6          [OperationContract(IsOneWay= false  )]
   7           void  Divide( double  x,  double   y);
   8       }
   9  
 10       public   interface   ICalculatorCallBack
  11       {
  12          [OperationContract(IsOneWay= false  )]
  13           void  CallBack( string   strMessage);
  14       }
  15  } 

我们定义了一个服务契约,里面有一个服务操作Divide,我们显式的设定isOneWay为false,那么它就是通过请求-回复模式进行工作的,或者说我们可以不设定这个值也是一样的。我们首先来看一下这个服务的wsdl是什么样子的把。

    1  <?xml version= "  1.0  "  encoding= "  utf-8  "  ?> 
   2  - <wsdl:definitions name= "  CalculatorService  "  targetNamespace= "  http://tempuri.org/  "  xmlns:wsdl= "  http://schemas.xmlsoap.org/wsdl/  "  xmlns:soap= "  http://schemas.xmlsoap.org/wsdl/soap/  "  xmlns:soapenc= "  http://schemas.xmlsoap.org/soap/encoding/  "  xmlns:wsu= "  http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd  "  xmlns:xsd= "  http://www.w3.org/2001/XMLSchema  "  xmlns:soap12= "  http://schemas.xmlsoap.org/wsdl/soap12/  "  xmlns:tns= "  http://tempuri.org/  "  xmlns:wsa= "  http://schemas.xmlsoap.org/ws/2004/08/addressing  "  xmlns:wsp= "  http://schemas.xmlsoap.org/ws/2004/09/policy  "  xmlns:wsap= "  http://schemas.xmlsoap.org/ws/2004/08/addressing/policy  "  xmlns:wsaw= "  http://www.w3.org/2006/05/addressing/wsdl  "  xmlns:msc= "  http://schemas.microsoft.com/ws/2005/12/wsdl/contract  "  xmlns:wsa10= "  http://www.w3.org/2005/08/addressing  "  xmlns:wsx= "  http://schemas.xmlsoap.org/ws/2004/09/mex  "  xmlns:wsam= "  http://www.w3.org/2007/05/addressing/metadata  " >
   3  - <wsp:Policy wsu:Id= "  WSDualHttpBinding_ICalculator_policy  " >
   4  - <wsp:ExactlyOne>
   5  - <wsp:All>
   6  - <wsrm:RMAssertion xmlns:wsrm= "  http://schemas.xmlsoap.org/ws/2005/02/rm/policy  " >
   7    <wsrm:InactivityTimeout Milliseconds= "  600000  "  /> 
   8    <wsrm:AcknowledgementInterval Milliseconds= "  200  "  /> 
   9    </wsrm:RMAssertion>
  10  - <sp:SymmetricBinding xmlns:sp= "  http://schemas.xmlsoap.org/ws/2005/07/securitypolicy  " >
  11  - <wsp:Policy>
  12  - <sp:ProtectionToken>
  13  - <wsp:Policy>
  14  - <sp:SecureConversationToken sp:IncludeToken= "  http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient  " >
  15  - <wsp:Policy>
  16    <sp:RequireDerivedKeys /> 
  17  - <sp:BootstrapPolicy>
  18  - <wsp:Policy>
  19  - <sp:SignedParts>
  20    <sp:Body /> 
  21    <sp:Header Name= "  ChannelInstance  "  Namespace= "  http://schemas.microsoft.com/ws/2005/02/duplex  "  /> 
  22    <sp:Header Name= "  To  "  Namespace= "  http://www.w3.org/2005/08/addressing  "  /> 
  23    <sp:Header Name= "  From  "  Namespace= "  http://www.w3.org/2005/08/addressing  "  /> 
  24    <sp:Header Name= "  FaultTo  "  Namespace= "  http://www.w3.org/2005/08/addressing  "  /> 
  25    <sp:Header Name= "  ReplyTo  "  Namespace= "  http://www.w3.org/2005/08/addressing  "  /> 
  26    <sp:Header Name= "  MessageID  "  Namespace= "  http://www.w3.org/2005/08/addressing  "  /> 
  27    <sp:Header Name= "  RelatesTo  "  Namespace= "  http://www.w3.org/2005/08/addressing  "  /> 
  28    <sp:Header Name= "  Action  "  Namespace= "  http://www.w3.org/2005/08/addressing  "  /> 
  29    </sp:SignedParts>
  30  - <sp:EncryptedParts>
  31    <sp:Body /> 
  32    </sp:EncryptedParts>
  33  - <sp:SymmetricBinding>
  34  - <wsp:Policy>
  35  - <sp:ProtectionToken>
  36  - <wsp:Policy>
  37  - <sp:SpnegoContextToken sp:IncludeToken= "  http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient  " >
  38  - <wsp:Policy>
  39    <sp:RequireDerivedKeys /> 
  40    </wsp:Policy>
  41    </sp:SpnegoContextToken>
  42    </wsp:Policy>
  43    </sp:ProtectionToken>
  44  - <sp:AlgorithmSuite>
  45  - <wsp:Policy>
  46    <sp:Basic256 /> 
  47    </wsp:Policy>
  48    </sp:AlgorithmSuite>
  49  - <sp:Layout>
  50  - <wsp:Policy>
  51    <sp:Strict /> 
  52    </wsp:Policy>
  53    </sp:Layout>
  54    <sp:IncludeTimestamp /> 
  55    <sp:EncryptSignature /> 
  56    <sp:OnlySignEntireHeadersAndBody /> 
  57    </wsp:Policy>
  58    </sp:SymmetricBinding>
  59  - <sp:Wss11>
  60    <wsp:Policy /> 
  61    </sp:Wss11>
  62  - <sp:Trust10>
  63  - <wsp:Policy>
  64    <sp:MustSupportIssuedTokens /> 
  65    <sp:RequireClientEntropy /> 
  66    <sp:RequireServerEntropy /> 
 

元数据有点长,但是不影响我们阅读。我们可以看到服务契约对应的是<portType>节点了,<portType>节点具有一系列的operation子元素表示定义在服务契约中的方法,而表示操作的<operation>节点通过输入<input>消息和输出<output>消息的有序组合来描述消息交换模式。

  1  -<wsdl:portType name= "  IName  " >
 2  -<wsdl:operation name= "  Write  " >
 3  <wsdl:input message= "  tns:IName_Write_InputMessage  "  wsaw:Action= "  http://tempuri.org/IName/Write  " />
 4  <wsdl:output message= "  tns:IName_Write_OutputMessage  "  wsaw:Action= "  http://tempuri.org/IName/WriteResponse  " /></wsdl:operation></wsdl:portType> 

 

 请求-回复消息模式通过operation节点的input和output元素来表示请求-回复的输入和输出消息。

 

void返回值 ,我们可以看到对于双工通信我们一般定义isOneWay为true,并且返回值为void,当然这里介绍的不是双工通信,所以我们来看一下返回值为void时,输入与输出又是什么呢?

对于请求-回复模式,输入参数列表决定了输入消息的格式,而输出消息的格式则由返回值的类型决定。对于void类型,因为只有输入没有返回值,但是wcf在请求-回复模式下依然会有返回值,只不过返回值的body 为空。

  1  -<sp:EncryptedParts>
 2  <sp:Body/>
 3  </sp:EncryptedParts> 

所以说在wcf中即使为void,也是要返回消息的,只不过消息主题部分为空。

还有一种形式就是out和ref 作为方法参数,wcf的消息会怎么样呢?其实想想 没事的时候想想怎些问题,还真是挺有趣的。

这个我们一起来探讨一下,

  1   namespace   Chinaer.WcfDemo.Contracts
  2   {
  3       [ServiceContract]
  4       public   interface   IName
  5       {
  6           [OperationContract]
  7           void  Write( out   string   name);
  8       }
  9  } 

   1   namespace   Chinaer.WcfDemo.Services
   2   {
   3      public   class   Name:IName
   4       {
   5           public   void  Write( out   string   name)
   6           {
   7              name =  "  guozhiiq  "  ;
   8           }
   9       }
  10  } 

   1  <?xml version= "  1.0  "  encoding= "  utf-8  " ?>
  2  <xs:schema xmlns:tns= "  http://tempuri.org/  "  elementFormDefault= "  qualified  "  targetNamespace= "  http://tempuri.org/  "  xmlns:xs= "  http://www.w3.org/2001/XMLSchema  " >
  3    <xs:element name= "  Write  " >
  4      <xs:complexType>
  5        <xs:sequence />
  6      </xs:complexType>
  7    </xs:element>
  8    <xs:element name= "  WriteResponse  " >
  9      <xs:complexType>
 10        <xs:sequence>
 11          <xs:element minOccurs= "  0  "  name= "  name  "  nillable= "  true  "  type= "  xs:string  "  />
 12        </xs:sequence>
 13      </xs:complexType>
 14    </xs:element>
 15  </xs:schema> 

 

 

请注意wsdl的格式,portType节点下依然有输出和输入两个子节点,但是是作为参数parameter进行传递的。我们把out换成ref看看是什么结果呢?

 

   1  <?xml version= "  1.0  "  encoding= "  utf-8  " ?>
  2  <xs:schema xmlns:tns= "  http://tempuri.org/  "  elementFormDefault= "  qualified  "  targetNamespace= "  http://tempuri.org/  "  xmlns:xs= "  http://www.w3.org/2001/XMLSchema  " >
  3    <xs:element name= "  Write  " >
  4      <xs:complexType>
  5        <xs:sequence>
  6          <xs:element minOccurs= "  0  "  name= "  name  "  nillable= "  true  "  type= "  xs:string  "  />
  7        </xs:sequence>
  8      </xs:complexType>
  9    </xs:element>
 10    <xs:element name= "  WriteResponse  " >
 11      <xs:complexType>
 12        <xs:sequence>
 13          <xs:element minOccurs= "  0  "  name= "  name  "  nillable= "  true  "  type= "  xs:string  "  />
 14        </xs:sequence>
 15      </xs:complexType>
 16    </xs:element>
 17  </xs:schema> 

 

各位看到out和ref的区别了吗?

服务契约中的操作只有输入和输出的概念,输入参数作为操作的输入,而输出参数和返回值作为操作的输出,而引用参数同时作为输入和输出。

这让我想到了一个概念,契约的等效性,什么是等效呢?不是说在.Net中定义的数据类型以及名称完全一样就可能称为等效?而是在生成的soap消息中的结构完全相同我们才成为等效。或者说生成的xml相同才是等效。我们可以利用attribute来更改属性在生成xml的name值,不是吗?

在上一篇博客 wcf基础知识之 查看soap消息 TcpTrace ,我有说到tcpTrace查看soap消息,其实还有其他更加简单的方法,当然这只能是在特殊场合下才可以使用。

如果你的宿主程序是svc,那么恭喜你,你可以不需要通过tcpTrace来查看soap消息了,在添加了服务引用以后,我们可以通过查看代码

 

通过查看对应服务的xml代码可以查看到soap消息,其实和tcpTrace截获的差不多,当然没有tcpTrace那么完整,但是可以很方便的让我们查看到大部分soap消息。当然这只适应svc文件。

 

 

每天进步一点,一年就会进步一大步,十年就可以成功,君子当自强不息,君子当好好学习,每天进步

 

分类:  Wcf

作者: Leo_wl

    

出处: http://www.cnblogs.com/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于消息交换模式 response/reply oneway deplex的详细内容...

  阅读:51次