WCF讲解

      因为项目的需要,开始学习WCF,对于WCF,本人只能算作刚刚开始学习,算入门级水平,整理这篇blog,希望给后来学习者一个借鉴,少走些弯路。

 

     本篇文章从入门开始,先讲解基础知识,然后讲解实现方法,采用了对比的方式进行了介绍,最后说明一些其他方法。

 

一、基础知识

    

      WCF(windows communication fundation),微软出的一套SOA的框架,它整合了微软之前的MQ,.NETREMOTING,web service等多种技术,但是整合的同时,确降低了开发的难度,这一点在刚开始学习的是否,并未体会,但是在实践的过程中,开始有了体会。

 

      概念:

      契约:也就是contract,包括 ServiceContract,OperationContract,DataContract,DataMember,MessageContract(这个暂时未用),FaultContract(暂时未用到)等等,这个其实就是一个特定,通知FRAMEWORK,声明了这些特性的类,或者成员,具有了WCF所要求的传输特性和公开特性。

 

     EndPoint:也就是断点,在wcf当中,客户端和主机端的通信,采用的其实是端到端的通信方式,也就是要求每个服务端与客户端需要有一个监听的端口,那么这个模式,采用了EndPoint的端点设计方式,也就是说,要求服务端提供断点,客户端连接端点,从而实现了相互通信。

 

    EndPoint包括三个成员,包括地址,绑定,契约,地址,很显然服务端需要发布一个地址,客户端需要连接这个地址才能够通信。绑定,这个概念的出现是为了方便传输控制,因为实际的世界中,分为局域网和广域网,那么传输时就需要考虑具体的适用协议,一般而言,局域网内传输建议tcp,广域网传输建议http。因此就出现了NetTcpBinding,wsHttpBinding,basicHttpBinding。契约,就是通知客户端,我这个端口,对外发布了一个什么样子的服务。

 

     绑定名称                                                                        简要介绍                                                       所需.Net Framework版本

    basicHttpBinding                                                    基于WS-I Basic Profile 1.1的Web服务                                  3.0

    wsHttpBinding                                                       针对改进的Web服务的绑定,包括WS-Security,

                                                                                   WS-Transaction等元素                                                         3.0

   wsDualHttpBinding                                                 提供双工通信的HTTP绑定                                                        3.0

   webHttpBinding                                                      支持REST/POX服务的绑定,使用XML/JSON序列化                      3.0

   netTcpBinding                                                          使用TCP传输协议在跨主机的局域网内使用,支持可靠性、

                                                                                   事务、安全等特性、并且该绑定被特别优化来支持WCF系统。

                                                                                   但是,使用该绑定需要确保通信双方都基于WCF构建,这里

                                                                                   并不符合SOA的原则                                                                3.0

   netNamedPipeBinding                                             支持和netTcpBinding大致相同的特性,

                                                                                   但由于使用命名管道进行通信,所以通信不能跨越主机                      3.0

   netMsmqBinding                                                     使用微软消息队列(MSMQ)协议来进行异步脱机的消息交互。

                                                                                   关于该绑定的交互方式,在本书的后续章节中有详细的介绍               3.0

   netPeerTcpBinding                                                 使用P2P协议在网格中进行消息交互                                             3.0

   msmqIntegrationBinding                                         该绑定可以用来在WCF消息和MSMQ消息中进行转换                       3.0

   wsFederationHttpBinding                                        该绑定支持使用了联合安全机制的Web服务                                   3.0

   ws2007HttpBinding                                                该绑定继承自wsHttpBinding,其主要涉及目的是为了支持

                                                                                   2007年新制定的WS标准                                                            3.5

   ws2007FederationHttpBinding                                 该绑定继承自wsFederationHttpBinding,和wsHttpBinding一样,

                                                                                    其设计目的是为了支持2007年新制定的WS标准

 

    宿主:之所以存在这个概念,是因为所谓的WCF是无法单独存在的,必须寄宿在一个进程当中,对外发布服务和监听地址。所谓宿主其实就是一个进程。那么进程的模式可以是console程序,app程序,还可以是windows service服务,wcf还可以支持IIS的宿主,提供广域网特性支持。

 

    元数据:服务的元数据描述服务的特征,外部实体需要了解这些特征以便与该服务进行通信。服务所公开的元数据包括XML架构文档(用于定义服务的数据协定)和WSDL文档(用于描述服务的方法)。启用元数据后,WCF通过检查服务及其终节点自动生成服务的元数据。

    上述这段话是抄来的,但是阅读完之后的进一步理解是这样的,对于WCF服务而言,他需要向外部发布,然后客户端才可以使用,那么客户端如何才知道服务的基本特性哪,就是需要通过元数据的描述,将服务特性进行说明,特征包括了数据契约和服务契约。

 

 二、实现方法

 

    WCF的实现,其实是分为两个部分的,一个是服务端的实现,一个是客户端的实现。

 

服务端实现:从实现的策略上来讲,分为两种实现方式,可以通过vs2010的WCF模板实现WCF服务,也可以通过手工实现(手工实现也足够简单)。

 

1、VS2010的WCF模板实现,该方法实现的其实就是一个WCF的服务DLL,其中包括了接口和实现类,并未提供宿主,宿主的实现仍然需要自己实现。

2、手工实现,该方法其实就是添加类库程序,即普通的DLL,然后分别实现接口类和实现类即可。宿主也是要自己实现的。

 

宿主实现方式:一共分为两种方法,一种是IIS,一种是selfhost方案,IIS未涉及,暂时不讲解。

selfhost的方案:console和winservice方案,两者其实根本实现原理上是一样的。具体内容

方法一,通过APP.CONFIG实现宿主的实现,在APP.CONFIG当中,写入endpoint信息,和metadatebehavior信息,然后再程序中直接创建serviceHost对象创建。

方法二,不通过app.config实现,而是直接在程序中,创建servicehost所需要的,URI,ENDPOINTADDRESS信息,然后利用servicehost的构造函数,创建对象。

 

客户端的实现:方法有二:一种是通过app.config,然后在该文件当中写明具体的client标签,然后填写服务端的endpoint信息。另一种是通过程序代码提供的方法。

通过程序代码的方式实现也有两种方法,一种是使用ClientBase<T>集成接口,然后直接调用该对象实现。另一种是通过ChannelFactory的方案实现proxy代理。

关键代码如下:

 

public partial class CalculatorClient :System.ServiceModel.ClientBase<ICalculator>, ICalculator

{

   

   public CalculatorClient()

    {

    }

   

   public CalculatorClient(string endpointConfigurationName) :

           base(endpointConfigurationName)

    {

    }

   

   public CalculatorClient(string endpointConfigurationName, stringremoteAddress) :

           base(endpointConfigurationName,remoteAddress)

    {

    }

   

   public CalculatorClient(string endpointConfigurationName,System.ServiceModel.EndpointAddress remoteAddress) :

           base(endpointConfigurationName, remoteAddress)

    {

    }

   

   public CalculatorClient(System.ServiceModel.Channels.Binding binding,System.ServiceModel.EndpointAddress remoteAddress) :

           base(binding, remoteAddress)

    {

    }

   

   public double Add(double n1, double n2)

    {

       return base.Channel.Add(n1, n2);

    }

}

 

在main方法中的使用:

 class WCFClient

    {

       static void Main()

       {

           //Step 1: Create an endpoint address and an instance of the WCF Client.

           CalculatorClient client = new CalculatorClient();

}

}

 

通道的方案如下:

 

ChannelFactory<ICalculateService>channel= newChannelFactory<ICalculateService>("CalculateService");

 

ICalculateService  proxy = channel.CreateChannle();

 

proxy.Add();

 

 

三、其他

 

服务契约:例子

 

   using System.ServiceModel ;

 

   [ServiceContract]

   public interface IService1

    {

       [OperationContract]

       string HelloWord(string name);

   }

   

   public class Service1 : IService1

    {

       public string HelloWord(string name)

       {

           return name + "说:HelloWord";

        }

   }

 

数据契约例子:

using System.ServiceModel ;

using System.Runtime.Serialization ;

 

   [DataContract]

   public class People

    {

       [DataMember]

       public string name;

       [DataMember]

       public int age;

 

       public People(string name,int age)

       {

           this.name = name;

           this.age = age;

       }

    }

 

数据契约使用

   [ServiceContract]

   public interface IService1

    {

       [OperationContract]

       string GetInfomation(People people);

    }

 

说明:对于enum类型其实是可以序列化的,因此可以直接应用到数据契约当中。对于自定义类型如果包含一个其他自定义类型,那么被包含的类型也必须支持数据契约,并使用KnowType(typeof())属性,确定该类型是可以被识别的。

 

服务契约,可以提供name属性,用于描述服务名称,namespace属性,用于描述服务的命名空间。

 

操作契约:

这是一种,oneway模式,就是客户端只需要调用,不需要知道返回值。并且是阻塞式的,需要等待执行的完成,才会返回。

 [OperationContract(IsOneWay=true)]

 void Test();

在请求响应模式中,客户端发送一个消息并且接收一个返回消息来完成一次交互。在该模式中,消息的发起端必然是客户端,并且从服务端返回只有一条消息。客户端在发送出消息后会阻止当前线程并且等待服务端返回消息。

[OperationContract]

       void Test();

双工模式(Duplex)

在双工模式中,客户端和服务端都可以任意地向对方发送消息,而对方也可以以任意的次序来接收消息。在这种模式下,发送端和接收端的概念变得不再适用,取而代之的是通信的两个端点。

 

 public interface ICallBack

    {

       [OperationContract(IsOneWay = true )]

       void UpdateInterval(int seconds);

    }

   [ServiceContract(CallbackContract=typeof(ICallBack ))]

   public interface IService1

    {

       [OperationContract]

       void Heartbeat();

    }

 

1.   在配置文件中设置绑定

<?xml version="1.0"encoding="utf-8" ?>

<configuration>

 <system.web>

   <compilation debug="true" />  

 </system.web>

 <system.serviceModel>

   <services>

     <servicename="WcfServiceLibrary1.Service1"behaviorConfiguration="WcfServiceLibrary1.Service1Behavior">

       <endpoint address ="HelloWord "                        

                  binding="wsHttpBinding"                      

                  contract="WcfServiceLibrary1.IService1">     

       </endpoint>

     </service>

   </services>

 </system.serviceModel>

</configuration>

 

2.   在代码中设置绑定

using System.ServiceModel;

using System.ServiceModel.Channels;

           NetNamedPipeBinding binding = new NetNamedPipeBinding ();

           EndpointAddress address = new EndpointAddress(newUri("net.pipe://localhost/HelloWorld "));

           using (HelloWorldProxy proxy = new HelloWorldProxy())

           {

               Console.WriteLine(proxy.HelloWorld("Kevin"));       //利用代理调用服务

                Console.Read();

           }

 

 

WCF的异常处理:

 

[ServiceContract]

   public interface IService1

    {

       [OperationContract]

       int Add(int a, int b);

}

   public class Service1 : IService1

    {

       public int Add(int a, int b)

       {

           throw new Exception("错误");

       }

}

 

客户端是可以接收到异常信息的,WCF的通用异常处理方法是首先服务端将异常转换为SOAP,然后发送给客户端,客户端接收到后,再转换为exception类型。但是,通常情况下,是无法获得有意义的错误信息的。因此WCF当中,提供了一个叫做FaultContractAttribute的契约。

 

 [ServiceContract]

   public interface IService1

    {

       [OperationContract]

       [FaultContract(typeof(FaultMessage))]

       int Add(inta,int b);

    }

 

   [DataContract]

   public class FaultMessage

    {

       [DataMember]

       public string Message;

 

       [DataMember]

       public interrorCode;

}

   public class Service1 : IService1

    {

       public int Add(int a, int b)

       {

           FaultMessage  faultMessage = newFaultMessage();

           faultMessage.Message = "错误信息";

           faultMessage.errorCode = 1234;

           throw new FaultException<FaultMessage>(faultMessage,faultMessage.Message);

       }

}

 

客户端的异常信息

Unhandled Exception:System.ServiceModel.FaultException`1[Client.ServiceReferenc

e1.FaultMessage]: 错误信息 (FaultDetail is equal to Client.ServiceReference1.Fa

ultMessage).

注意:由于单程操作没有任何返回值,也不回把任何错误发还给客户端,所以不能在单程操作上使用错误契约,不然会导致运行时异常。

 

 

消息契约

使用数据契约已经足以应付消息交互双方对数据内容的所有要求,但是对消息的格式却无法全面控制。如果想要定制SOAP消息的Head和Body内容,这就需要定制SOAP消息的Head和Body内容,这就需要用到消息契约。消息契约在实际WCF编程中使用的并不多,本节不做详细讨论,只给出一个简单的示例:

   [MessageContract ]

   public interface MyMessage

    {

       [MessageHeader ]

       public intSessionId;

       [MessageHeader]

       public string Description;

       [MessageBodyMember ]

       public string A;

        [MessageBodyMember]

       public string B;

       [MessageBodyMember]

       public string C;

}

说明:消息中包含Header跟Body两部分。Header用来存放上下文信息,Body用来存放数据信息。

 

 

关于WCF的session和instancecontextmode的实现对比表:

 

 

 

public enumSessionMode
        { 
           Allowed = 0,   允许会话模式
           Required = 1,  必须会话模式
           NotAllowed = 2 必须不支持会话模式
        }

 

public enumInstanceContextMode
    { 
       PerSession =  0 ,   会话模式
       PerCall = 1 ,    每次调用一个服务实例模式
       Single = 2       单例模式
}

 

 

 

并发处理,其实是一个并发控制,本质是多线程

public enumConcurrencyMode
        { 
           Single = 0,
           Reentrant = 1,
           Multiple = 2
        }

 

 

Single并发模式
ConcurrentMode.Single并发模式是默认的并发设置,当设置了Single模式以后,WCF会为服务实例的操作提供同步锁。Single并发模式的策略较为极端,等同于在整个操作上加上了同步锁,在很多情况下,这并不是必须的。

Multiple并发模式
ConcurrentMode.Multiple表示WCF不会主动为服务操作添加任何锁,每个操作都允许客户端多个请求同时访问,这样做的好处是提高了系统的运行效率,防止消息被阻塞。
Reentrant并发模式
本质上,ConcurrentMode.Reentrant与ConcurrentMode.Single模式一样:在同一时间只允许一个线程访问服务操作,在访问进入操作之前必须获得同步锁。所不同的是,ConcurrentMode.Reentrant模式解决了ConcurrentMode.Single模式的死锁问题。
实际上ConcurrentMode.Reentrant模式的设计正是为了解决死锁问题。当服务操作在调用其它服务,或者回调客户端操作时,会释放服务端的同步锁,这样就能够保证在回调消息返回或者调用链回到服务端时不会发生死锁。在一些消息量较大,服务操作中较长时间访问其它操作的情况下,ConcurrentMode.Reentrant模式能够有效的保证配对消息能够在服务操作向外调用时进入操作。

 

WCF回调

 

      回调处理,相信很多人都可能会用到,主要的目的是完成客户端和服务端的相互调用,WCF肯定是会考虑这个问题的。那么对于WCF的回调处理,其本质的想法是,一个流程的处理。

 

 

总结:

1、 必须使用支持双向通信的绑定如NetTcpBinding、NetNamedPipeBinding,注意wxHttpBinding是不支持的。

2、 要在服务契约定义的服务接口中,定义回调接口。

例:

 [ServiceContract(CallbackContract = typeof(ISomeCallbackContract))]

  Public interface ICalculateService

{

}

 

 Public interface ISomeCallbackContract

{

}

3、在服务的实现类当中,需要获取该接口,并使用该接口,获取的方法其实跟获取sessionId的方法很相似,都是通过ISomeCallbackContract callback  =OperationContext.Current.GetCallbackChannel<ISomeCallbackContract >();callback.SomeCallbackMethod2();

4、客户端生成代理以后,由客户端去实现回调接口

例:

      public class CallBack : ISomeCallbackContract

      {

        //实现接口

       }

5、在客户端需要实现该接口,基本的实现方法,是首先实现Clientbase<>类的继承关系,然后通过base获取一个InstanceContext的具体实例,然后再通过构造函数就可以直接创建。

ISomeCallbackContract callback = new CallBack();

InstanceContext context = new InstanceContext(callback);

SampleServiceClientproxy= new SampleServiceClient();

sc.DoSomething();

 

WCF全面解析(套装上下册)》由蒋金楠所著,是作者多年潜心研究WCF技术的心血之作,也是这些年来从事WCF开发的经验总结。书如其名,此书涵盖了WCF几乎所有的知识点,并对其底层框架进行了“庖丁解牛”式的剖析,力求将WCF的整个运行机制完整而清晰地呈现在读者面前。 《WCF全面解析(套装上下册)》上册的前四章在对WCF进行总体介绍的基础上,对构成终结点的三要素(地址、绑定和契约)进行了系统说明;随后的两章则着重剖析序列化和消息编码在WCF中的实现;第7、8章讲述了在服务寄宿和操作调用过程中,WCF的服务端和客户端框架分别为我们做了什么;第9、10章将介绍的重点落在实例化、会话和REST服务上面;在最后一章中采用WCF构建了一个具体的电子商务网站VM,它将指导你如何将理论应用于实践。 《WCF全面解析(套装上下册)》的下册主要涉及一些所谓的“高级”话题,主要包括如何在分布式环境中处理异常(第1章);元数据的导入与导出、发布与获取如何实现(第2章);如何利用WCF对事务的支持将分布式事务引入服务(第3章);如何利用并发与限流机制提高服务的吞吐量和可用性(第4章);如何利用可靠会话机制确保消息的“使命必达”(第5章);如何利用队列服务提供离线通信的支持(第6章);第7、8章主要涉及安全的相关内容,包括传输安全、授权与审核;第9章全景展示WCF服务端和客户端的运行时框架,以及在此基础上的所有扩展可能;最后一章为你带来WCF4.0几个独立的新特性。 编辑推荐 《WCF全面解析(套装上下册)》不仅适合尚未接触过WCF,希望尽快入门并进行深入研究的开发人员使用,同样也适合对WCF有一定了解的开发设计人员和架构师阅读。相信不同层次的读者都能从此书中找到自己希望了解的部分。 《WCF全面解析(套装上下册)》的内容不仅适合尚未接触过WCF,希望尽快入门并进行深入研究的开发人员,同样适合对WCF具有一定了解的开发设计人员和架构师。相信不同层次的读者都能从本书中找到自己希望了解的部分。阅读本书的读者需要对.NET,包括对C#和.NET Framework具有一定的了解。如果读者具备了DCOM、Enterprise Library Service、.NET Remoting、Web Service、MSMQ及SOA相关的基础,对阅读此书尽快掌握WCF将大有裨益。 名人推荐我经历了COM时代,一直把Don Box的《COMM本质论》奉为我的指路明灯。能把SOA机理和WCF这种特定厂商实现的技术讲得如《COM本质论》一样完美透彻的,那必属Artech这本经过自己深研、实践而著的心血结晶——《WCF全面解析》。如果你想成为SOA和WCF方面的专家,那么这本书就是你的最好法宝。想想你作为专家而获得的回报,那么你对这本书购买所付出的,简直是太值了。 ——《走出软件作坊》 作者 明源软件CTO 阿朱 首先,金楠是—位工作在一线的优秀的WCF技术人员,这符合我对阅读技术图书的第一个要求和期待。其次,金楠的写作文笔、专业责任也给人以充分信任,这在金楠的文字中读者可以体会。这本《WCF全面解析》全面剖析了构建WCF应用所需要的各方面技术,剥丝抽茧,由浅入深,也是我非常欣赏的技术讲述方式。我相信《WCF全面解析》—书是搞WCF朋友的案头必备。 ——祝成科技与Boolan.com创始人.NET技术专家 李建忠 知识全面、论述准确、逻辑严密是本书的特点。这是一本各层次开发人员都可以从中受益的书:对于初、中级开发人员,它可以帮助你获得WCF全方位的知识,系统地梳理WCF的知识结构,提升动手实践能力;对于高级开发人员,它既可以有效弥补你WCF相关知识中的盲点,又可以让你在自己熟悉的知识点上领略作者的看法和理解。 ——资深架构师 曲春雨 作者简介蒋金楠,网名Artech,现就职于某知名软件公司担任高级软件顾问。连续5届微软MVP(最有价值专家),同时也是少数的双料MVP(Solutions Architecture+Connected System)之一。国内较早接触WCF的人之一,2007年2月起在个人博客(http://www.cnblogs.com/artech)上发表超过两百篇深入介绍WCF的文章,成为了目前国内WCF在线资料的主要来源。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值