3.2.1 服务寄宿对绑定的指定
当我们通过一个托管的应用程序对一个服务进行自我寄宿的时候,一般会为服务创建一个ServiceHost对象,然后通过ServiceHost的AddServiceEndpoint方法为之添一个或多个终结点。ServiceHost和基类ServiceHostBase定义一个了若干重载的AddServiceEndpoint方法,每个方法都包含一个Binding对象。下面的代码片断列出了所有定义在ServiceHost和ServiceHostBase中的AddServiceEndpoint方法。
public abstract class ServiceHostBase { //其他成员 public ServiceEndpoint AddServiceEndpoint(string implementedContract, Binding binding, string address); public ServiceEndpoint AddServiceEndpoint(string implementedContract, Binding binding, Uri address); public ServiceEndpoint AddServiceEndpoint(string implementedContract, Binding binding, string address, Uri listenUri); public ServiceEndpoint AddServiceEndpoint(string implementedContract, Binding binding, Uri address, Uri listenUri); }
public abstract class ServiceHost { //其他成员 public ServiceEndpoint AddServiceEndpoint(Type implementedContract, Binding binding, string address); public ServiceEndpoint AddServiceEndpoint(Type implementedContract, Binding binding, Uri address); public ServiceEndpoint AddServiceEndpoint(Type implementedContract, Binding binding, string address, Uri listenUri);
public ServiceEndpoint AddServiceEndpoint(Type implementedContract,
Binding binding, Uri address, Uri listenUri);
}
在下面的代码中,为CalculatorService服务添加了3个终结点,这3个终结点对应的绑定类型分别为:BasicHttpBinding、WsHttpBinding和NetTcpBinding。
namespace Artech.WcfServices.Hosting { class Program { static void Main(string[] args) { using (ServiceHost serviceHost = new ServiceHost (typeof(CalculatorService))) { serviceHost.AddServiceEndpoint(typeof(ICalculator), new BasicHttpBinding(), "http://127.0.0.1:6666/ CalculatorService"); serviceHost.AddServiceEndpoint(typeof(ICalculator), new WSHttpBinding(), "http://127.0.0.1:7777/ CalculatorService"); serviceHost.AddServiceEndpoint(typeof(ICalculator), new NetTcpBinding(),"net.tcp://127.0.0.1:8888/ CalculatorService"); serviceHost.Open(); Console.Read(); } } } }
任何一种绑定类型对应着一种确定的传输方式,比如BasicHttpBinding和WsHttpBinding采用HTTP传输协议;NetTcpBinding采用TCP;NetMsmqBinding采用MSMQ的传输方式。当我们创建终结点的时候,绑定对象和指定的地址必须相互匹配,否则将会抛出异常。比如在下面的代码中,为一个基于BasicHttpBinding的终结点指定了一个NET.TCP地址,当ServiceHost的Open方法被执行的时候将会抛出一个如图3-7的ArgumentExcetion异常。
图3-7 URI与绑定不匹配时的异常
using (ServiceHost serviceHost = new ServiceHost(typeof(CalculatorService))) { serviceHost.AddServiceEndpoint(typeof(ICalculator), new BasicHttpBinding(), "net.tcp://127.0.0.1:8888/CalculatorService"); serviceHost.Open(); //其他操作 }
当我们采用基地址/相对地址的方式对服务进行寄宿的时候,对于终结点中指定的相对地址,WCF会在对应的ServiceHost基地址列表中寻找传输协议和与绑定类型相匹配的基地址,两者相互组合构成完整的终结点地址。比如,在下面的代码中,为服务CalculatorService添加了两个基地址:http://127.0.0.1:8888和net.tcp://127.0.0.1:9999。并通过AddServiceEndpoint方法添加了两个终结点,这不同的终结点具有不同的绑定类型(WsHttpBinding和NetTcpBinding)和相同的相对地址(CalculatorService)。WCF会根据绑定的具体类型,在基地址列表中寻找与传输协议匹配的基地址,基地址和相对地址相互组合,构成最终的终结点地址。在此例中,WsHttpBinding对应的终结点地址为http://127.0.0.1:888/CalculatorService,NetTcpBinding对应的终结点地址为net.tcp://127.0.0.1:9999/CalculatorService。
namespace Artech.WcfServices.Hosting { class Program { static void Main(string[] args) { Uri[] baseAddresses = new Uri[] { new Uri("http://127.0.0.1:8888"), new Uri("net.tcp://127.0.0.1:9999") }; using (ServiceHost serviceHost = new ServiceHost(typeof(CalculatorService), baseAddresses)) { serviceHost.AddServiceEndpoint(typeof(ICalculator), new WSHttpBinding(), "CalculatorService"); serviceHost.AddServiceEndpoint(typeof(ICalculator), new NetTcpBinding(), "CalculatorService"); serviceHost.Open(); Console.Read(); } } } }
当进行服务寄宿的时候,在执行ServiceHost的Open方法之前,可以为绑定对象进行相应的定制,设置相关的属性。在下面的代码片断中,为服务添加终结点之前,先创建了一个BasicHttpBinding对象,并设置了该对象相应的属性(AllowCookie、HostNameComparisonMode和MaxBufferPoolSize)。
namespace Artech.WcfServices.Hosting { class Program { static void Main(string[] args) { using (ServiceHost serviceHost = new ServiceHost (typeof(CalculatorService))) { BasicHttpBinding binding = new BasicHttpBinding(); binding.AllowCookies = true; binding.HostNameComparisonMode = HostNameComparisonMode.Exact; binding.MaxBufferPoolSize = 3721; serviceHost.AddServiceEndpoint(typeof(ICalculator), binding, "http://127.0.0.1:8888/CalculatorService"); serviceHost.Open(); Console.Read(); } } } }
终结点的绑定也可以通过配置的方式进行指定,绑定的类型可以直接通过终结点配置节的binding属性进行配置,比如通过下面的配置,为CalculatorService添加了3个终结点,它们分别采用了3种不同类型的绑定:BasicHttpBinding、WsHttpBinding和NetTcpBinding。
<?xml version="1.0" encoding="utf-8" ?> <configuration> <system.serviceModel> <services> <service name="Artech.WcfServices.Services.CalculatorService"> <endpoint address="http://127.0.0.1:6666/CalculatorService" binding="basicHttpBinding" contract="Artech.WcfServices.Contracts.ICalculator" /> <endpoint address="http://127.0.0.1:7777/CalculatorService" binding="wsHttpBinding" bindingConfiguration="" contract="Artech.WcfServices. Contracts.ICalculator" /> <endpoint address="net.tcp://127.0.0.1:8888/ CalculatorService" binding="netTcpBinding" bindingConfiguration="" contract= "Artech.WcfServices.Contracts.ICalculator" /> </service> </services> </system.serviceModel> </configuration>
所有的绑定对象都具有一些共同的属性,比如OpenTimeout、CloseTimeout、SendTimeout、ReceiveTimeout等。此外,不同的绑定对象也有一些专属于自己的属性。如果没有显式地对这些属性进行设置,那么将采用这些属性的默认值。如果希望通过配置的方式对绑定对象进行定制,须要将相关设置定义在binding列表中。下面的配置中,在<bindings>/<basicHttpBinding>中添加了一个BasicHttpBinding,并为其指定了一系列的属性,并将该BasicHttpBinding命名为“MyBinding”,在具体的终结点中,通过bindingConfiguration根据名称对绑定进行引用。
<?xml version="1.0" encoding="utf-8" ?> <configuration> <system.serviceModel> <bindings> <basicHttpBinding> <binding name="MyBinding" openTimeout="00:05:00" receiveTimeout="00:15:00" sendTimeout="00:15:00" allowCookies="true" /> </basicHttpBinding> </bindings> <services> <service name="Artech.WcfServices.Services.CalculatorService"> <endpoint address="http://127.0.0.1:6666/CalculatorService" binding="basicHttpBinding" bindingConfiguration="MyBinding" contract="Artech.WcfServices.Contracts.ICalculator" /> </service> </services> </system.serviceModel> </configuration>