閱讀331 返回首頁    go 技術社區[雲棲]


[原創]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

image

圖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。

image 

圖2 基於TCP的IIS服務寄宿實例在VS2008中的解決方案結構

本實例仍然采用我們熟悉的計算服務的例子,在Contracts項目下,定義了接口ICalculator代表計算服務的服務契約。

1: using System.ServiceModel;
2: 
3: namespace Artech.WasHostingDemo.Contracts
4: {
5:     [ServiceContract(Namespace="https://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>

進行非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所示。

image

 

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

作者:蔣金楠
微信公眾賬號:大內老A
微博:www.weibo.com/artech
如果你想及時得到個人撰寫文章以及著作的消息推送,或者想看看個人推薦的技術資料,可以掃描左邊二維碼(或者長按識別二維碼)關注個人公眾號(原來公眾帳號蔣金楠的自媒體將會停用)。
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁麵明顯位置給出原文連接,否則保留追究法律責任的權利。
原文鏈接

最後更新:2017-10-30 14:34:24

  上一篇:go  使用阿裏雲虛擬主機時,網站文件上傳到哪個目錄下?
  下一篇:go  WCF技術剖析之四:基於IIS的WCF服務寄宿(Hosting)實現揭秘