一、服务
服务是一组公开功能的集合。
服务内部包含了如语言、技术、版本与框架等概念,服务之间的交互只允许使用规定的通信模式
外界客户端并不知道服务内部的实现细节,所以WCF服务通常通过元数据的方式描述可用的功能及服务可能采用的通信方式
WCF不允许客户端直接与服务交互,客户端总是使用代理将调用转发给服务 ,WCF允许客户端跨越执行边界与服务通信,如跨应用程序域、进程甚至网络。
WCF要求客户端对本地对象还是远程对象都保持一致的编程模型,而不用考虑服务的位置
WCF对本地对象还是远程对象都使用代理调用服务,大大简化了应用程序的编程模型,使用代理可以拦截WCF的请求,增加WCF的价值
二、地址
在WCF中,每个服务都有一个唯一的地址(Address)。
地址包含两个重要的元素:服务位置及传输协议。
服务位置包含目标机器名、站点、通信端口、管道?(或队列),以及一个可选的特定路径或URI。
-
WCF支持下列传输协议
-
HTTP/HTTPS
- HTTP地址可以使用http/https协议传输。如:
- http://localhost:81
- HTTP地址默认端口为80,HTTPS则为443。
- HTTP地址可以共享一个端口,甚至一台机器
-
TCP
- TCP地址采用net.tcp协议进行传?输,通常它还包括端口。如:
- net.tcp://localhost:81/MyService
- TCP默认端口号为808
- 两个TCP地址可以共享一个端口
-
IPC
- IPC(进程间通信)地址使用net.pipe协议进行传输,它将使用Windows的命名管道机制。
- 在WCF中命名管道机制的服务只能接受来自同一台机器?的调用,使用时必须指定明确的本地机器名或者直接命名为localhost,为管道名提供唯一的标识字符串:
- net.pipe://localhost/MyPipe
- 在同一台机器只能打开一个命名通道,因此,两个命名通道地址在同一台机器上不能共用一个管道名。
Peer network(对等网)
-
MSMQ
- MSMQ地址使用net.msmq协议进行传?输,即使用微软消息队列机制。
- 使用时必须为MSSQ地址指定队列名。如果是处理私?有队列,则必须指定队列类型,但是对公有队列,队列类型可以?省略:
- net.msmq://localhost/private/MyService
- net.msmq://localhost/MyService
-
Service bus
- Windows Azure AppFabric服务总线使用sb、http或https协议传输
- 服务总线地址必须包括服务命名空间。如:
- sb://MyNameSpace.servicebus.windows.net/
-
-
地址通信通常采用以下格式
[基地址]/[可选的URI]
-
基地址通常采用以下格式
-
[传输协议]://[机器名或域名][:可选端口]
- 如下一些地址通信示例
- http://localhost:81
- http://localhost:81/MyService
- net.tcp://localhost:81/MyService
- ......
- 如下一些地址通信示例
-
三、契约
WCF的所有服务都会公开为契约(Contract)
契约与平台无关,是描述服务功能的标注方式
-
服务契约(Service Contract)
- 服务契约描述了客户端能够执行的服务操作。
-
数据契约(Data Contract)
- 数据契约定义了与服务交?互的数据类型。
- WCF把内建类型隐式定义为数据契约,也可以将自定义类型定义为数据契约
-
错误契约(Fault Contract)
- 错误契约定义了服务抛出的错误,以及服?务处理错误和传递错误到客户端的方式
-
消息契约(Message Contract)
- 消息契约允许服务直接与?消息交互,可以是类型化的,也可以是非类型化的。
- 倘若消息交互的另一端规定了某些显式(通常是专有的)消息格式,在这种要求互操作性的?场景下,消息契约将非常有用。
四、绑定
绑定是开发人员控制WCF程序与其他消息交互的主要手段。从功能上看,绑定创建了通道工厂惑通道侦听器的堆栈对象。绑定直接惑间接创建的对象是WCF实现各种消息功能(例如,传输、安全性、事务性)的主要方式。一个绑定封装了诸如传输协议、消息编码、通信模式、可靠性、安全性、事务传播,以及互操作性等相关选项,使得它们保持一致。
-
五种常用绑定
-
基本绑定
- 对应BasicHttpBinding类
- 基本绑定能够将WCF服务公开为传统的ASMX Web服务,使得原客户端能够与新的服务协作
-
TCP绑定
- 对于NetTcpBinding类
- TCP绑定使用TCP协议实现在Intranet中跨机器的通信,支持多种特性,包括可靠性、事务性、安全性,以及WCF之间通信的优化,前提是它要求客户端与服务都必须使用WCF
-
IPC绑定
- 对应NetNamePipeBingding类
- 他使用命名管道为同一机器通信进行传输
- 这种绑定最安全,因为它不是接受来自机器外的调用
- 它是性能最佳的绑定,因为IPC协议比TCP协议更加简单
-
Web服务(WS)绑定
- 对应于WSHttpBinding类
- WS绑定使用Http和Https进?行传输,为基于Intranet的通信提供多种特性(如可靠性、事务性和安全性),这些特性均遵循WS-*标准
- 该绑定用来与支持WS-*标准的系统进行互操作
-
MSMQ绑定
- 对应与NetMsmqBinding类
- 使用MSMQ进行传输,用于支持断开的队列调用
-
-
格式与编码
-
WCF标准绑定
名称 传输协议 编码 互操作性 BasicHttpBinding HTTP/HTTPS Text + NetTcpBinding TCP Binary - NetNamedPipeBinding IPC Binary - WSHttpBinding HTTP/HTTPS Text,MTOM + NetMsmqBinding MSMQ Binary -
- 文本编码通常允许WCF服务(或客户端)能够通过HTTP协议与其他服务(或客户端)通信,而不用考虑它所使用的技术及通信传输的范围
- 二进制编码格式通过TCP、IPC或MSMQ可以获得最佳的性能,但它是以牺牲或操作性为代价,只支持WCF到WCF的通信
-
-
选择绑定
- 选择绑定决策图
- .
- 选择绑定决策图
-
其他绑定
- WCF还提供了3种特例,即BasicHttpContextBindingg、WSHttpContextBinding和NetTcpContextBinding
- 上下文绑定均继承自它们各自的常?规绑定,并添加上下文协议的支持。上下文协议允许开发者传递带参数到服务
六、托管
每个WCF服务都必须托管在Windows进程中,该进程称为宿主进程(host process)
单个宿主进程可以托管多个服务,相同的服务类型也可以托管在多个宿主进程中
-
IIS 5/6 托管
- 在IIS Web服务器中托管服务的主要优势是宿主进程可以在客户端第一次请求时自动启动,还可以借助IIS 5/6 管理宿主进程的生命周期。
- IIS 托管的主要缺点在于只能使用HTTP协议。如果是IIS 5,则还受限于端口,要求所有服务必须使用相同的端口号。
-
自托管
- 自托管(Self-Hosting)是由开发者提供和管理宿主进程生命周期的一种方式。
- 当客户端与服务器之间的进程有明确边界时,使用自托管。如两者处于相同进程时,可使用进程内托管。
- 自托管服务可以使用任意WCF传?输协议,而且可以使用WCF的高级特性
-
WAS托管
- IIS 5/6是一个Web服?务器,而不是托管引擎。在IIS 5/6里托管WCF服?务非常不稳定,需要经常重启Web服务器,还只能?使用HTTP协议。
- WAS(Windows激活服务)是通用的?宿主引擎,可以托管网站(IIS 7默认使用WAS托?管网站),可以方便地托管服务,允许使用任何传?输协议,可以单独安装配置WAS,不需要和IIS 7一?起使用。
- WAS属于系统服务,所以不需要提?前启动宿主进程。当第一个调用到达时,WAS会拦?截这个调用消息,启动一个工作进程还托管服务,然后把调用消?息转发。
- WAS可以在WIndows Vista、Winodws Server 2008和Windows 7及后续版本中使用。
-
IIS/WAS里的自定义托管
- 1.为了解决IIS 5/6或?WAS中需要直接与宿主交互的问题,WCF提?供了叫做"宿主工厂"的hook。?在.svc文件里直接使用Factory标签,?可以提供自定义创建宿主的类:
<%@ ServiceHost Language="C#" Debug="true" Service="ch01.Service1" CodeBehind="Service1.svc.cs"Factory="MyServiceFactory" %>
- 2.如果不使用.svc文件,也可以在?配置文件中指定宿主工厂:
<serviceActivations>
<add relativeAddress ="MyService.svc" service="MyService" factory="MyServiceFactory"/>
</serviceActivations> - 3.宿主工厂必须继承ServiceHostFactory类,?并重写CreateServiceHost()虚方法:
class NyServiceFactory:ServiceHostFactory
{
protected override ServiceHost CreateServiceHost(Type serviceType,Uri[] baseAddress)
{
ServiceHost host = new ServiceHost(serviceType,baseAddress);
//自定义步骤
return host;
}
}
- CreateServiceHost()方法逻辑上是IIS或?WAS托管服务中的Main()方法,可以使?用它来做这个工作。
- 1.为了解决IIS 5/6或?WAS中需要直接与宿主交互的问题,WCF提?供了叫做"宿主工厂"的hook。?在.svc文件里直接使用Factory标签,?可以提供自定义创建宿主的类:
-
Windows Server AppFabric
- WAS是个通用的宿主引擎,它实际上并不知道托管的是WCF服务,还是网站,对WCF服务也不会做什么优化。
- 为了处理这个问题,可以安装WAS扩展程序,即Windows Server AppFabric。
- Windows Server AppFabric需要IIS 7.5,要求机器是Windows7、Winodws Server 2008 R2 及.NET 4.0。
- Windows Server AppFabric的设计目标就是为WCF或WF提供监控、显示,以及时间跟踪等额外的配置选项。
- 对于WCF开发文员来说,最重要的Windows Server AppFabric功能应该是它在不等待第一个客?户端请求到来时就可以自动启动服务。当需要服务不依赖于客户端请求到来而自动启动时,可以通过Windows Server AppFabric来启动服务。
-
选择宿主
- 对于Internet应用程序,可以依据下图来做决定:
- 对于Intranet应用可以依据下图决定:
- 对于Internet应用程序,可以依据下图来做决定:
七、终结点
服务与地址、绑定和契约有关。
地址定义了服务的位置,绑定定义了服务的通信方式,契约则定义了服务的内容。称为”服务的ABC“。
WCF用终结点表示这样一组关系。终结点是地址、绑定和契约的一种混合品。
每一个终结点都包含这三个元素,而宿主则负责公开终结点。
每个服务至少公开一个业务终结点,每个终结点有且只有一个服务契约。
以文件方式配置终结点
以管理方式配置终结点需要将终结点信息放到托管进程的配置文件中,例如下面给出的服务定义:
namespace MyNamespace
{
[ServiceContract]
interface IMyContract
{....}
class MyContract:IMyContract
{....}
}下面演示了配置文件要求的配置入口:
<system.serviceModel>
<services>
<service name="MyNamespace.MyService">
<endpoint
address="http://localhost:8000/MyService"
binding="wsHttpBinding"
contract="MyNamespace.IMyContract"
/>
</service>
</services>
</system.serviceModel>当指定服务和契约类型时,必须使用类型全名
使用基地址
<system.serviceModel>
<services>
<service name="MyNamespace.MyService">
<host>
<baseAddress>
<add baseAddress="http://localhost:8000/"/>
</baseAddress>
</host>
<endpoint
address="MyService"
binding="wsHttpBinding"
contract="MyNamespace.IMyContract"
/>
</service>
</services>
</system.serviceModel>如果宿主没有提供匹配的基地址,则在装载服务时会抛出异常。配置终结点地址时,可以为基地址添加相对URI.
绑定配置
使用配置文件可以设置终结点使用的绑定。因此,需要在endpoint节上添加bindingConfguration属性。下面演示了启用事务传播的方法:
<system.serviceModel>
<services>
<service name="MyNamespace.MyService">
<endpoint
address="net.tcp://localhost:8000/MyService"
bindingConfiguration="TransactionalTCP"
binding="wsHttpBinding"
contract="MyNamespace.IMyContract"
/>
</service>
</services>
<bindings>
<netTcpBinding>
<biinding name="TransactionalTCP" transactionFlow="true"/>
</netTcpBinding>
</bindings>
</system.serviceModel>
默认绑定
WCF允许使用默认绑定。默认绑定会影响使用此配置文件的应用程序的所有服务。默认绑定不需要使用名称。如下:
<netTcpBinding>
<biinding transactionFlow="true"/>
</netTcpBinding>
默认绑定会作用在所有没有显式配置的终结点上。如下:
<system.serviceModel>
<services>
<service name="MyNamespace.MyService">
<endpoint
address="net.tcp://localhost:8000/MyService"
binding="wsHttpBinding"
contract="MyNamespace.IMyContract"
/>
</service>
</services>
<bindings>
<netTcpBinding>
<biinding transactionFlow="true"/>
</netTcpBinding>
</bindings>
</system.serviceModel>每个绑定类型最多有一个默认绑定。
以编程方式配置终结点
以编程方式配置终结点是通过编程调用将终结点添加到ServiceHost实例中。ServiceHost定义了多个重载版本的AddServiceEndpoint()方法。
ServiceHost host = new ServiceHost(typeof (MyService));
BasicHttpBinding bind = new BasicHttpBinding();
host.AddServiceEndpoint(typeof (IMyervice), bind,"http://localhost:8000/MyService");
host.Open();
使用基地址
Uri httpBaseAddress = new Uri("http://localhost:8000/");
ServiceHost host = new ServiceHost(typeof (MyService),httpBaseAddress);
BasicHttpBinding bind = new BasicHttpBinding();
//使用基地址
host.AddServiceEndpoint(typeof(IMyervice) , bind , "");
//使用相对地址
host.AddServiceEndpoint(typeof (IMyervice), bind, "MyService");
//忽略基地址
host.AddServiceEndpoint(typeof(IMyervice) , bind , "http://localhost:8000/MyService");
host.Open();
绑定配置
ServiceHost host = new ServiceHost(typeof (MyService));
NetTcpBinding tcp = new NetTcpBinding();
tcp.TransactionFlow = true;
host.AddServiceEndpoint(typeof(IMyervice) , tcp , "net.tcp://localhost:8000/MyService");
host.Open();
默认终结点
如果服务宿主没定义终结点,只提供了一个基地址,则WCF将会为服务添加默认的终结点,即默认终结点。
WCF会为每个基地址、每个契约添加终结点,使用基地址作为服务地址。
WCF会根据基地址的scheme来推断绑定类型。对于HTTP,WCF使用basic绑定。
默认绑定会影响默认终结点,WCF也会通过连接绑定和契约来命名终结点。
也可以使用ServiceHost的AddDefaultEndpoints()方法明确添加默认终结点。
协议映射
对于默认终结点,WCF会使用基地址的scheme来推测绑定类型。这个推测过程成为协议映射。
加入是TCP、IPC和MSMQ,则只有一个映射选择。但是,对于HTTP(或HTTPS),WCF默认使用basic绑定,则要在配置文件里使用protoclMapping节点来设置:<protocolMapping>
<add binding="basicHttpsBinding" scheme="https" />
</protocolMapping>也可以指定专门的绑定方式:
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https" bindingConfiguration="..." />
</protocolMapping>必须在配置文件里定义协议映射。
参考资料:《WCF服务编程》