[原创]WCF技术剖析之三:如何进行基于非HTTP的IIS服务寄宿

上面一篇文章中,我们对不同版本的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;
2: 
3: namespace Artech.WasHostingDemo.Contracts
4: {
5:     [ServiceContract(Namespace="http://www.artech.com/")]
6:    public interface ICalculator
7:     {
8:         [OperationContract]
9:        double Add(double x, double y);
0:     }
1: }

在Services项目中,实现了ICalculator接口,提供服务的实现:

1: using Artech.WasHostingDemo.Contracts;
2: 
3: namespace Artech.WasHostingDemo.Services
4: {
5:    public class CalculatorService:ICalculator
6:     {
7:         #region ICalculator Members
8: 
9:         public double Add(double x, double y)
0:         {
1:             return x + y;
2:         }
3: 
4:         #endregion
5:     }
6: }

和普通基于HTTP的IIS服务寄宿一样,我们需要为WCF服务创建相应的.SVC文本文件,该文件一般仅仅包含一个<%@ ServiceHost%>指令。简单起见,我仅仅添加了唯一一个必需的Service属性(Attribute)。我把该文件命名为CalculatorService.svc,下面是该.SVC的全部内容:

<%@ ServiceHost Service="Artech.WasHostingDemo.Services.CalculatorService,Artech.WasHostingDemo.Services"%>

然后,将Services所在的目录映射为IIS下的虚拟目录。在本例中,在IIS 7的Default Web Site站点下,创建了一个命名为WasHostingDemo的Web应用,并将其物理地址指定为Services项目所在的目录。然后在根目录下创建一个Web.config,配置WCF服务寄宿相关的设置。整个WCF配置如下,Binding类型指定为NetTcpBinding。

1: <?xml version="1.0" encoding="utf-8" ?>
2: <configuration>
3:     <system.serviceModel>
4:         <services>
5:             <service name="Artech.WasHostingDemo.Services.CalculatorService">
6:                 <endpoint address="" binding="netTcpBinding" bindingConfiguration=""
7:                     contract="Artech.WasHostingDemo.Contracts.ICalculator" />
8:             </service>
9:         </services>
0:     </system.serviceModel>
1: </configuration>

注:由于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:*']

站点绑定添加于修改也可以直接通过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

步骤三:创建客户端程序进行服务调用

对于调用非HTTP协议的IIS寄宿服务的客户端来说,和普通的WCF服务调用完全一样,下面是服务调用代码和相关的配置。由于,客户端程序通过访问WCF服务的.SVC文件的方式进行服务的调用,所以在相应终结点中的地址为.SVC所在的地址。

1: using System;
2: using System.ServiceModel;
3: using Artech.WasHostingDemo.Contracts;
4: 
5: namespace Artech.WasHostingDemo.Client
6: {
7:     class Program
8:     {
9:         static void Main(string[] args)
0:         {
1:             using (ChannelFactory<ICalculator> channelFactory = new ChannelFactory<ICalculator>("calculatorservice"))
2:             {
3:                 ICalculator calculator = channelFactory.CreateChannel();
4:                 using (calculator as IDisposable)
5:                 {
6:                     try
7:                     {
8:                         Console.WriteLine("x + y = {2} when x = {0} and y = {1}", 1, 2, calculator.Add(1, 2));
9:                     }
0:                     catch (CommunicationException)
1:                     {
2:                         (calculator as ICommunicationObject).Abort();
3:                         throw;
4:                     }
5:                     catch (TimeoutException)
6:                     {
7:                         (calculator as ICommunicationObject).Abort();
8:                         throw;
9:                     }
0:                 }
1:             }
2:         }
3:     }
4: } 
   1: <?xml version="1.0" encoding="utf-8" ?>
   2: <configuration>
   3:   <system.serviceModel>
   4:     <client>
   5:       <endpoint address="net.tcp://127.0.0.1/WasHostingDemo/CalculatorService.svc"
   6:       binding="netTcpBinding" bindingConfiguration="" contract="Artech.WasHostingDemo.Contracts.ICalculator"
   7:       name="calculatorservice" />
   8:     </client>
   9:   </system.serviceModel>
  10: </configuration>

通过运行客户端程序,你将得到如下的输出:

   1: x + y = 3 when x = 1 and y = 2

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Golang语言社区

package http

要管理代理、TLS配置、keep-alive、压缩和其他设置,创建一个Transport:

2304
来自专栏大内老A

[WCF权限控制]利用WCF自定义授权模式提供当前Principal[实例篇]

在《原理篇》中我们谈到:如果采用自定义安全主体权限模式,我们可以通过自定义AuthorizationPolicy或者ServiceAuthorizationMa...

26110
来自专栏大内老A

ASP.NET MVC集成EntLib实现“自动化”异常处理[实例篇]

个人觉得异常处理对于程序员来说是最为熟悉的同时也是最难掌握的。说它熟悉,因为仅仅就是try/catch/finally而已。说它难以掌握,则是因为很多开发人员却...

21710
来自专栏大内老A

回调与并发: 通过实例剖析WCF基于ConcurrencyMode.Reentrant模式下的并发控制机制

对于正常的服务调用,从客户端发送到服务端的请求消息最终会被WCF服务运行时分发到相应的封装了服务实例的InstanceContext上。而在回调场景中,我们同样...

1947
来自专栏逸鹏说道

Linux 部署ASP.NET SQLite 应用 的坎坷之旅 附demo及源码

Linux 部署ASP.NET SQLite 应用 的坎坷之旅。文章底部 附示例代码。 有一台闲置的Linux VPS,尝试着部署一下.NET 程序,结果就踏上...

3933
来自专栏大内老A

[WCF REST] 通过ASP.NET Output Caching实现声明式缓存

ASP.NET的输出缓存(Output Caching)机制允许我们针对整个Web页面或者页面的某个部分(主要针对用户控件)最终呈现的HTML进行缓存。对于后续...

1916
来自专栏一个爱瞎折腾的程序猿

asp.net core使用Swashbuckle.AspNetCore(swagger)生成接口文档

开局一张图,然后开始编,一些基本的asp.net core东西就不再赘述,本文只对Swashbuckle.AspNetCore的几个使用要点进行描述。

1771
来自专栏恒思考

一个人的app后端-parse的安装与使用

mkdir -p ~/mongo ~/mongo/db cd ./mongo/ docker run -p 27017:27017 -v ~/mongo/db:...

2593
来自专栏阿杜的世界

Spring的容器内部事件发布自定义事件机制Spring 的容器内事件发布类结构应用场景

EventListener接口的作用仅仅在于“标记”,具体要提供哪些功能需要开发者自己定义,而且,还需要为自己定义的接口提供一个默认的实现类——只有接口的话什么...

1022
来自专栏一个爱瞎折腾的程序猿

在asp.net core2.1中添加中间件以扩展Swashbuckle.AspNetCore3.0支持简单的文档访问权限控制

在此之前的接口项目中,若使用了 Swashbuckle.AspNetCore,都是控制其只在开发环境使用,不会就这样将其发布到生产环境(安全第一) 。 那么,...

1731

扫码关注云+社区

领取腾讯云代金券