代码改变世界

WCF理论 【转载】

2015-09-01 14:10  悠悠鑫宝  阅读(159)  评论(0编辑  收藏  举报

原文地址:http://blog.itpub.net/23109131/viewspace-661613/

 

WCF是什么?

WCF是"Windows Communication Foundation "的缩写,利用它能够开发出分布式(Distributed)应用程序,使用它能创建安全的(Secure)、可靠的(Reliable)、跨平台的(transacted messaging along with interoperability)的分布式解决方案。它可以支持跨应用程序域(AppDomain),进程(Process),网络(NetWork)的进行数据通讯,而且能寄宿在诸如IIS,Windows Service,Console,Windows Application等多种宿主(Host)中。而且开发难度相比以前的.Net Remoting和Asp.Net Xml Web Service等都有了大幅度的降低。其最大的特征在于1)充分整合了原来的.Net Remoting,Asp.Net Xml,WebService,MSMQ,WSE,Enterprise Service等多项分布式技术,取其精华,弃其糟粕。2)WCF虽然整合了几项技术,但开发难度不增反降,简单易学。

WCF能干什么?

在win32中,应用程序是运行在进程(Process)的线程(Thread)中的,.Net平台出现之后,出现了AppDomain,其实就相当于在进程和线程之间又有了一层包装,类似于子进程的概念,在一个进程(或者应用程序域)中的对象能进行直接的访问和控制,但超出这个范围,便不能进行直接的访问和控制了,所以说进程(或者应用程序域)有一定的隔离作用,如果是分布在不同网络,不同操作系统上的不同进程,他们进行通讯的难度就更大,而分布式应用程序要求的就是将原本被隔离的作用域通过一定的契约联系起来,从而达成多个系统的沟通协作。当然能实现这种目的的方式远不止WCF一个,比如在win32时代,经常使用映射内存文件来实现进程之间的互操作问题,还有在windows程序中,用windows消息wm也能实现不同进程之间的通讯问题,但这些都有局限性,因为他们不能很好的解决跨平台,跨网络问题,而WCF可以。

WCF与其他分布式技术区别

 

Xml Web Service

.Net Remoting

Enterprice Service

WSE

MSMQ

WCF

跨平台

       

.Net与.Net通讯

 

     

分布式事务

   

   

安全可靠性

     

 

消息队列

       

 

WCF似乎等于前面几项技术之和,它还具有自己的优点:1。统一性,2。互操作性,3。安全可靠,4。兼容性

WCF在安全性方面做的改进

为了保证数据通讯的安全,WCF提供了三种保护措施:1)机密性(Confidentiality)2)完整性(Integrity) 3)可验证性(Authentication),这三种措施联合起来被称为CIA。并且这些措施在WCF中是默认支持的。机密性能保证传输的数据是经过加密的,不被非法监听(eavesdrop),而完整性利用数字签名技术防止数据在传输过程中被注入(injected)或篡改(tampered),而验证(Authentication)可以采用灵活的策略来处理达到的客户端请求,比如用户名密码验证,客户端证书验证等。

为了跟踪Web Service和WCF的消息,我们还需要了解一下两个工具:

  1. Microsoft SOAP Toolkit Version 3 中的 Trace Utility 不能跟踪WCF报文
  2. tcpTrace

原来一直用Trace Utilty来跟踪xml web service的消息报文,非常好用,它能按包显示出Soap信息,看起来也非常方便。有关它的消息,请从http://www.microsoft.com/downloads/details.aspx?FamilyId=C943C0DD-CEEC-4088-9753-86F052EC8450&displaylang=en 上下载SOAP Toolkit 3.0,安装后,便出现了这个工具,在跟踪xml web service的消息报文的时候,这个工具很好用,但跟踪wcf的报文却不行,能截获到数据,但每个报文都是空的,可能也和wcf报文是经过加密的有关系吧,同时建议大家使用tcpTrace.

WCF在性能方面有那些改进?

分别测试循环1000次对wcf和xml web service相同功能方法的调用,得到如下的数据:

  WCF Web Service
第一次 9523ms 7561ms
第二次 9480ms 7465ms
第三次 9508ms 7708ms
第四次 9487ms 7900ms

 

经过四次测试数据,我们可以得出,wcf的性能和xml web service相比的确要低,但差别不大,肯定在一个数量级之上。

什么是契约?

任何一个分布式应用程序,它之所以能够互相传递消息,都是事先制定好数据交换规则的,这个规则正是交换数据的双方(比如服务器端和客户端)能彼此理解对方的依据,WCF作为分布式开发技术的一种,同样具有这样一种特性。而在WCF中制定的的规则就被称之为契约(Contract),它是WCF的消息标准,是任何一个wcf程序不可或缺的一部分。

在WCF中,契约分为四种,它们分别为:

  • 用于定义服务操作的服务契约:Service Contract 
    这种级别的契约又包括两种:ServiceContract和OperationContract 
    ServiceContract用于类或者结构上,用于指示WCF此类或者结构能够被远程调用,而OperationContract用于类中的方法(Method)上,用于指示WCF该方法可被远程调用。
  • 用于自定义数据结构的数据契约:Data Contract 
    数据契约也分为两种:DataContract和DataMember.DataContract用于类或者结构上,指示 WCF此类或者结构能够被序列化并传输,而DataMember只能用在类或者结构的属性(Property)或者字段(Field)上,指示WCF该属性或者字段能够被序列化传输。
  • 用于自定错误异常的异常契约:Fault Contract 
    FaultContract用于自定义错误异常的处理方式,默认情况下,当服务端抛出异常的时候,客户端能接收到异常信息的描述,但这些描述往往格式统一,有时比较难以从中获取有用的信息,此时,我们可以自定义异常消息的格式,将我们关心的消息放到错误消息中传递给客户端,此时需要在方法上添加自定义一个错误消息的类,然后在要处理异常的函数上加上FaultContract,并将异常信息指示返回为自定义格式。
  • 用于控制消息格式的消息契约:Message Contract 
    简单的说,它能自定义消息格式,包括消息头,消息体,还能指示是否对消息内容进行加密和签名。

如何定义契约?

其实上面落里罗嗦说了一大堆,似乎契约使用起来应该很难的样子了,可事实上,契约的使用是很简单的,它无非就是在普通的程序结构上添加一些声明性的属性就可以了,比如我们可以直接在类上声明ServerContractAttribute,此时这个类就能被远程客户端访问到,而在类中的方法中(Method)添加OperationContractAttribute就能将方法暴露给远程客户端,其他的契约也一样的用法,比较难得还是消息契约和错误契约,当也很简单。我这里没有WCF开发环境,所以具体怎么用,我就不做示例了,您仍不明白的话,可以参考下面几篇文章:

http://www.cnblogs.com/artech/archive/2007/02/28/659331.html

http://www.rainsts.net/article.asp?id=427

http://www.rainsts.net/article.asp?id=429

http://www.rainsts.net/article.asp?id=430

WCF作为一种能够跨平台的体系框架,独立于平台之外,它只约束通讯的双方应该遵守什么样的规则,而丝毫不管双方各自采用的是什么样的技术和什么样的操作系统,也就是说如果有异构,异网的情况,根本不影响WCF。

Address是什么?

一个要和服务端通讯的客户端要做的第一件事情,就是搞清数据要发给谁?目的地在哪?而Address正是通过一个Uri来唯一标示一个WCF的终节点(EndPoint)的,它标示了消息发送的目的地。在WCF 数据通讯中,它解决了服务在哪里的问题。

Address的组成?

Address在WCF中的用System.ServiceModel.EndpointAddress对象来表示的,它的结构如下:

此外,Address还包括IsAnonymous属性,用于指示终节点是否能匿名访问。

如何在配置文件中指定Address?

在配置文件中,有两种方式可以指定Address,一种是绝对地址方式,另外是相对地址方式,分别如下:

绝对地址

 <host>
          <baseAddresses>
            <add baseAddress = "http://localhost:8731/" />
          baseAddresses>
   host>
   <endpoint address ="http://localhost:8731/Service" binding="basicHttpBinding"
 contract="Wcf_Address_Config.IService1"> endpoint>

相对地址

 <host>
          <baseAddresses>
            <add baseAddress = "http://localhost:8731/" />
          baseAddresses>
  host>
  <endpoint address ="Service1" binding="basicHttpBinding" 
      contract="Wcf_Address_Config.IService1">endpoint>

在网上有人说绝对地址是通过将httpGetEnabled设置为true,并且设置httpGetUrl为绝对地址是在设置endPoint的说法有些不准确,因为在WCF中有两种地址,一种是访问endPoint时候用到地址,另外一种是服务描述的地址,服务描述在wcf中被称作serviceMetadata,通过它能够产生代理类,比如,我们做如下的设置:

 <serviceMetadata httpGetEnabled="True" httpGetUrl="http://localhost:8731/Service"/>

只代表在http://localhost:8731/Service/?wsdl上能找到服务描述,可以通过http://localhost:8731/Service/?wsdl生成代理类,而不是将endPoint的地址设置为了http://localhost:8731/Service,这点一定要注意,不要受有些说法的误导。

如何通过编程方式设置Address?

除了能在配置中设置Address外 ,还可以通过编程的方式来设置Address,具体方法请参参见下面的代码示例:

 static void Main(string[] args)
        {
            EndpointAddress address = new EndpointAddress("http://127.0.0.1:2136/Service1");           
            Binding binding = new BasicHttpBinding();
            wcf.IService1 service = new wcf.Service1Client(binding, address);
            Console.WriteLine(service.GetData(2));
            Console.Read();
        }

上面的代码就是将endPoint的地址设置为了http://127.0.0.1:2136/Service1

Address有什么特殊应用?

在wcf中,能够将服务同时发布到几个地址上面,只要这些地址采用的都是一种访问方式。这种一份程序,多个发布地址的做法,在以往的技术中是没有的。

WCF相关文章http://www.csharpwin.com/search.aspx?ChID=0&AID=0&KW=WCF

WCF技术研究团http://wcfs.cnblogs.com/