在上面一篇文章中,我们对不同版本的IIS,以及ASP.NET得的实现机制进行了详细而深入的分析。在介绍IIS7.0的时候,我们谈到,HTTP.SYS+W3SVC实现了基于HTTP的请求监听,在此基础上引入了以下三组网络监听器(Listener)和监听适配器(Adapter),实现了基于TCP、Named Pipes和MSMQ的网络监听,图1 揭示了IIS7的总体结构。
TCPListener|TCP Listener Adapter
NamedPipes Listener|Named Pipes Listener Adapter
MSMQ Listener|MSMQ Listener Adapter
图1 IIS 7总体架构
由于IIS 7提供了基于非HTTP网络协议的监听支持,那么就意味着当我们当我们通过IIS进行WCF服务寄宿(Hosting)的时候,可以采用非HTTP的通信方式。在本篇文章中,我们将通过一个简单实例介绍进行非HTTP的IIS服务寄宿,Source Code下载WasHostingDemo.zip。
由于IIS 7在本质上通过WAS(Windows Process Activation Service)实现了非HTTP的请求监听,我们也可以将这种方式的服务寄宿称为基于WAS的服务寄宿。在本实例中,我们通过IIS 7实现基于TCP的服务寄宿,图2 表示实例应用在VS2008种的解决方案结构。其中,Class Library类型的项目Contracts用于定义服务契约;而Services则用于定义具体的服务;Console应用项目Client模拟客户端。此外,Services对应目录被映射为IIS相应站点下的某个Web应用,虚拟目录名称为WasHostingDemo。
图2 基于TCP的IIS服务寄宿实例在VS2008中的解决方案结构
步骤一:定义服务契约和服务
本实例仍然采用我们熟悉的计算服务的例子,在Contracts项目下,定义了接口ICalculator代表计算服务的服务契约。
1: using System.ServiceModel;
<!--CRLF-->2:
<!--CRLF-->3: namespace Artech.WasHostingDemo.Contracts
<!--CRLF-->4: {
<!--CRLF-->5: [ServiceContract(Namespace="http://www.artech.com/" )]
<!--CRLF-->6: public interface ICalculator
<!--CRLF-->7: {
<!--CRLF-->8: [OperationContract]
<!--CRLF-->9: double Add(double x, double y);
<!--CRLF-->0: }
<!--CRLF-->1: }
<!--CRLF-->
在Services项目中,实现了ICalculator接口,提供服务的实现:
1: using Artech.WasHostingDemo.Contracts;
<!--CRLF-->2:
<!--CRLF-->3: namespace Artech.WasHostingDemo.Services
<!--CRLF-->4: {
<!--CRLF-->5: public class CalculatorService:ICalculator
<!--CRLF-->6: {
<!--CRLF-->7: #region ICalculator Members
<!--CRLF-->8:
<!--CRLF-->9: public double Add(double x, double y)
<!--CRLF-->0: {
<!--CRLF-->1: return x + y;
<!--CRLF-->2: }
<!--CRLF-->3:
<!--CRLF-->4: #endregion
<!--CRLF-->5: }
<!--CRLF-->6: }
<!--CRLF-->
和普通基于HTTP的IIS服务寄宿一样,我们需要为WCF服务创建相应的.SVC文本文件,该文件一般仅仅包含一个<%@ ServiceHost%>指令。简单起见,我仅仅添加了唯一一个必需的Service属性(Attribute)。我把该文件命名为CalculatorService.svc,下面是该.SVC的全部内容:
<%@ ServiceHost Service="Artech.WasHostingDemo.Services.CalculatorService,Artech.WasHostingDemo.Services" %>
<!--CRLF-->
然后,将Services所在的目录映射为IIS下的虚拟目录。在本例中,在IIS 7的Default Web Site站点下,创建了一个命名为WasHostingDemo的Web应用,并将其物理地址指定为Services项目所在的目录。然后在根目录下创建一个Web.config,配置WCF服务寄宿相关的设置。整个WCF配置如下,Binding类型指定为NetTcpBinding。
1: <? xml version ="1.0" encoding ="utf-8" ?>
<!--CRLF-->2: < configuration >
<!--CRLF-->3: < system.serviceModel >
<!--CRLF-->4: < services >
<!--CRLF-->5: < service name ="Artech.WasHostingDemo.Services.CalculatorService" >
<!--CRLF-->6: < endpoint address ="" binding ="netTcpBinding" bindingConfiguration =""
<!--CRLF-->7: contract ="Artech.WasHostingDemo.Contracts.ICalculator" />
<!--CRLF-->8: </ service >
<!--CRLF-->9: </ services >
<!--CRLF-->0: </ system.serviceModel >
<!--CRLF-->1: </ configuration >
<!--CRLF-->
注:由于ASP.NET应用在运行的时候默认从根目录下的Bin子目录加载Assembly,而Services项目默认编译的目标目录为Bin\Debug|Release,所以我们需要通过修改项目属性将编译的目标目录设为Bin。
步骤二:为站点设置TCP绑定,为Web应用添加支持协议
进行非HTTP的服务寄宿是WAS为WCF提供的最显著的特性。由于在默认的情况下,IIS仅仅支持对于HTTP请求的处理,我们需要相应的方式对IIS相关配置进行相关的修改,从而改变IIS默认的请求处理行为。在上面我们说过,IIS 7.0广泛采用了基于XML文件的配置方式,所以最终极的方式就是直接修改相应的配置文件。但是,直接修改配置文件的方式,出错的频率很高,对于很多的配置,我们都可以直接通过IIS管理器进行相应的修改。此外,我们可以选择通过命令行的方式修改相应的配置,IIS为我们提供了一系列的命令。
WAS的配置保存在配置文件applicationHost.config中,该文件保存在%windir%\system32\inetsrv\config目录中。为了实现基于非HTTP的服务寄宿,首先需要做的是为WCF Service的寄宿应用所在的Web Site添加非相应非HTTP协议的站点绑定(site binding),该操作可以通过执行Appcmd.exe命名实现,该命名存放在%windir%\system32\inetsrv\目录中。
为了使寄宿WCF服务的Web站点具有基于TCP的监听能力,我们可以通过下面的命名行为该站点(Default Web Site)添加基于TCP的绑定,指定监听端口为808(默认端口)。
appcmd.exe set site "Default Web Site" -+bindings.[protocol='net.tcp',bindingInformation='808:*']
<!--CRLF-->
站点绑定添加于修改也可以直接通过IIS管理器进行:选择相应站点=〉在右边的部分“Bindings”=〉在弹出的Site Bindings对话框中可以添加新的站点绑定和编辑现有的站点绑定,如图3所示。
图 3 通过 IIS 管理器设置站点绑定
在站点级别非HTTP绑定存在的情况下,你还可在应用级别控制对非HTTP协议的支持。在默认的情况下,Web应用并不提供对非HTTP协议的支持,你需要通过AppCmd.exe为应用添加对于某个非HTTP协议支持的能力。通过下面的配置对默认站点下的WasHostingDemo应用添加了对net.tcp支持的能力。
appcmd.exe set app "Default Web Site/WasHostingDemo" /enabledProtocols:net.tcp
<!--CRLF-->
步骤三:创建客户端程序进行服务调用
对于调用非HTTP协议的IIS寄宿服务的客户端来说,和普通的WCF服务调用完全一样,下面是服务调用代码和相关的配置。由于,客户端程序通过访问WCF服务的.SVC文件的方式进行服务的调用,所以在相应终结点中的地址为.SVC所在的地址。
1: using System;
<!--CRLF-->2: using System.ServiceModel;
<!--CRLF-->3: using Artech.WasHostingDemo.Contracts;
<!--CRLF-->4:
<!--CRLF-->5: namespace Artech.WasHostingDemo.Client
<!--CRLF-->6: {
<!--CRLF-->7: class Program
<!--CRLF-->8: {
<!--CRLF-->9: static void Main(string [] args)
<!--CRLF-->0: {
<!--CRLF-->1: using (ChannelFactory<ICalculator> channelFactory = new ChannelFactory<ICalculator>("calculatorservice" ))
<!--CRLF-->2: {
<!--CRLF-->3: ICalculator calculator = channelFactory.CreateChannel();
<!--CRLF-->4: using (calculator as IDisposable)
<!--CRLF-->5: {
<!--CRLF-->6: try
<!--CRLF-->7: {
<!--CRLF-->8: Console.WriteLine("x + y = {2} when x = {0} and y = {1}" , 1, 2, calculator.Add(1, 2));
<!--CRLF-->9: }
<!--CRLF-->0: catch (CommunicationException)
<!--CRLF-->1: {
<!--CRLF-->2: (calculator as ICommunicationObject).Abort();
<!--CRLF-->3: throw ;
<!--CRLF-->4: }
<!--CRLF-->5: catch (TimeoutException)
<!--CRLF-->6: {
<!--CRLF-->7: (calculator as ICommunicationObject).Abort();
<!--CRLF-->8: throw ;
<!--CRLF-->9: }
<!--CRLF-->0: }
<!--CRLF-->1: }
<!--CRLF-->2: }
<!--CRLF-->3: }
<!--CRLF-->4: }
<!--CRLF-->
1: <? xml version ="1.0" encoding ="utf-8" ?>
<!--CRLF--> 2: < configuration >
<!--CRLF--> 3: < system.serviceModel >
<!--CRLF--> 4: < client >
<!--CRLF--> 5: < endpoint address ="net.tcp://127.0.0.1/WasHostingDemo/CalculatorService.svc"
<!--CRLF--> 6: binding ="netTcpBinding" bindingConfiguration ="" contract ="Artech.WasHostingDemo.Contracts.ICalculator"
<!--CRLF--> 7: name ="calculatorservice" />
<!--CRLF--> 8: </ client >
<!--CRLF--> 9: </ system.serviceModel >
<!--CRLF--> 10: </ configuration >
<!--CRLF-->
通过运行客户端程序,你将得到如下的输出:
1: x + y = 3 when x = 1 and y = 2
<!--CRLF-->
注: 部分内容节选自《WCF技术剖析(卷1)》第八章:客户端(Clients)
WCF技术剖析系列:
WCF技术剖析之一:通过一个ASP.NET程序模拟WCF基础架构
WCF技术剖析之二:再谈IIS与ASP.NET管道
WCF技术剖析之三:如何进行基于非HTTP的IIS服务寄宿
WCF技术剖析之四:基于IIS的WCF服务寄宿(Hosting)实现揭秘
WCF技术剖析之五:利用ASP.NET兼容模式创建支持会话(Session)的WCF服务
WCF技术剖析之六:为什么在基于ASP.NET应用寄宿(Hosting)下配置的BaseAddress无效
WCF技术剖析之七:如何实现WCF与EnterLib PIAB、Unity之间的集成
WCF技术剖析之八:ClientBase<T>中对ChannelFactory<T>的缓存机制
WCF技术剖析之九:服务代理不能得到及时关闭会有什么后果?
WCF技术剖析之十:调用WCF服务的客户端应该如何进行异常处理
WCF技术剖析之十一:异步操作在WCF中的应用(上篇)
WCF技术剖析之十一:异步操作在WCF中的应用(下篇)
WCF技术剖析之十二:数据契约(Data Contract)和数据契约序列化器(DataContractSerializer)
WCF技术剖析之十三:序列化过程中的已知类型(Known Type)
WCF技术剖析之十四:泛型数据契约和集合数据契约(上篇)
WCF技术剖析之十四:泛型数据契约和集合数据契约(下篇)
WCF技术剖析之十五:数据契约代理(DataContractSurrogate)在序列化中的作用
WCF技术剖析之十六:数据契约的等效性和版本控制
运维网声明
1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网 享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com