WCF 採用net.tcp協議實踐

與Socket相比,WCF真是爽得不得了,其基本指導思想爲SOA——面向服務。

 

    其基本配置在於ABC(Address,Binding,Contract),通常,只要這三個因素配置對了,那麼,基本上就無限接近目標了。

    剩下的配置,就可能是行爲(Behavior),安全(Security)等。

 

    在所有綁定中,爲什麼要選擇net.tcp,是因爲其比較快(我這也是道聽途說,究竟有多快,沒有進行過測試);但是,缺點就是,net.tcp方式只能是WCF對WCF的通信。

 

    而其繁瑣複雜的配置,網上已經有諸多工程師做了很多無私的奉獻。

步驟

一、準備:首先iis必須是7.0或更高,同時需要安裝需要在“打開或關閉Windows功能”中安裝Microsoft .NET Framework 3.5.1中的Windows Communication Foundation HTTP Activation、Windows Communication Foundation Non-HTTP Activation和Web管理工具-IIS6管理兼容性-IIS元數據庫和IIS6配置兼容性這三個功能;(我的系統是win7旗艦版)

在iis中,我乾脆把所有的服務都安裝了。

二、配置網站支持nettcp協議
防火牆需要爲nettcp服務開洞,要允許端口:4502-4534通過

4502:*
 下面就可以創建你的網站虛擬目錄並確定啓用nettcp協議

(3)wcf在訪問的時候存在跨域問題,在wwwroot文件夾即網站跟目錄下放置跨域訪問文件和策略文件clientaccesspolicy.xml、crossdomain.xml。文件內容如下:
clientaccesspolicy.xml內容:

<?xml version="1.0" encoding="utf-8"?>
<access-policy>
  <cross-domain-access>
    <policy>
      <allow-from http-request-headers="*">
        <domain uri="*"/>
      </allow-from>
      <grant-to>
        <resource path="/" include-subpaths="true"/>
        <socket-resource port="4502-4530" protocol="tcp"/>
      </grant-to>
    </policy>
  </cross-domain-access>
</access-policy>
crossdomain.xml內容:

<?xml version="1.0"?>
<cross-domain-policy>
 <allow-access-from domain="*"/>
</cross-domain-policy>

Step1:設置“打開或關閉Windows功能”

    打開紅色框內的功能

CN1

Step2:設置IIS

選中Default Web Site ——點擊“綁定”——確保網站綁定對話框中有“net.tcp”(默認端口號808),如果沒有,則“添加”

image

選中項目——高級設置——確保有“net.tcp”

image

Step3:設置“服務”

image

Step4:設置配置文件

    只需將下文中的******替換即可。

S4.1服務端模板

    替換Address(主機名+端口+文件路徑形式的名稱);

    替換Contract(服務接口全名)

複製代碼
<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.serviceModel>
    <!--描述綁定-->
    <bindings>
      <netTcpBinding>
        <binding name="netTcpBindConfig" closeTimeout="00:30:00"
                openTimeout="00:30:00" receiveTimeout="00:30:00" sendTimeout="00:30:00"
                transactionFlow="false" transferMode="Buffered" transactionProtocol="OleTransactions"
                hostNameComparisonMode="StrongWildcard" listenBacklog="10"
                maxBufferPoolSize="2147483647" maxBufferSize="2147483647" maxConnections="10"
                maxReceivedMessageSize="2147483647">
          <readerQuotas maxDepth="2147483647"
                          maxStringContentLength="2147483647"
                          maxArrayLength="2147483647"
                          maxBytesPerRead="2147483647"
                          maxNameTableCharCount="2147483647" />
          <reliableSession ordered="true"  inactivityTimeout="00:01:00" enabled="false" />
          <security mode="None">
            <transport clientCredentialType="Windows" protectionLevel="EncryptAndSign"></transport>
            <message clientCredentialType="Windows" />
          </security>
        </binding>
      </netTcpBinding>
    </bindings>
    <!--描述服務-->
    <services>
      <service name="DataSync.Services.DataSyncServiceImpl" behaviorConfiguration="WFServiceBehavior">
        <host>
          <baseAddresses>
            <add baseAddress="net.tcp://localhost:808/DSServiceImpl"/>
          </baseAddresses>
        </host>
        <endpoint address=""
                  contract="DataSync.Interfaces.IDataSyncEntry"
                  binding="netTcpBinding"
                  bindingConfiguration="netTcpBindConfig" />
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
      </service>
    </services>
    <!--描述行爲-->
    <behaviors>
      <serviceBehaviors>
        <behavior name="WFServiceBehavior">
          <serviceMetadata httpGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="true"/>
          <dataContractSerializer maxItemsInObjectGraph="6553600"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>

  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
    <!--
        若要在調試過程中瀏覽 Web 應用程序根目錄,請將下面的值設置爲 True。
        在部署之前將該值設置爲 False 可避免泄露 Web 應用程序文件夾信息。
      -->
    <directoryBrowse enabled="true"/>
  </system.webServer>

  <system.web>
    <compilation debug="true" targetFramework="4.0" />
  </system.web>

</configuration>
複製代碼

 

S4.2客戶端模板

    替換Address(指定寄宿的地址,如****/***.svc,而不是上文的DSServiceImpl);

    替換Contract(服務接口全名)

複製代碼
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <system.serviceModel>
        <bindings>
            <netTcpBinding>
                <binding name="NetTcpBinding_IDataSyncEntry">
                    <security mode="None" />
                </binding>
            </netTcpBinding>
        </bindings>
        <client>
            <endpoint address="net.tcp://75wojoax/WcfWays/DataSyncServiceImpl.svc"
                binding="netTcpBinding" bindingConfiguration="NetTcpBinding_IDataSyncEntry"
                contract="Remote.IDataSyncEntry" name="NetTcpBinding_IDataSyncEntry" />
        </client>
    </system.serviceModel>
</configuration>
複製代碼

問題

P1 需重啓IIS

問題描述:未能從程序集“System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089”中加載類型“System.ServiceModel.Activation.HttpModule”。

解決辦法(執行以下命令,以重啓IIS):

如果安裝了 .NET Framework 4,隨後啓用了 .NET Framework 3.5 WCF HTTP 激活,則會發生此錯誤。若要解決該問題,請在 Visual Studio 2010 命令提示符下運行下面的命令行: aspnet_regiis.exe -i -enable 參見:http://msdn.microsoft.com/zh-cn/library/aa751852.aspx

 

P2 需匹配的協議

問題描述:找不到具有綁定 NetTcpBinding 的終結點的與方案 net.tcp 匹配的基址。註冊的基址方案是 [http]。

解決方案:確保服務端和客戶端均使用NetTcpBinding協議。

參考:http://www.cnblogs.com/liulun/archive/2011/11/25/2263873.html

 

P3需匹配的協議

問題描述:無法調度消息,因爲終結點地址“net.tcp://localhost/DataSyncServiceImpl.svc”上的服務對該地址的協議不可用。

解決方案:

1)確保服務端和客戶端均使用NetTcpBinding協議;

2)如果服務端使用了安全配置,如

<security mode="None">
  <transport clientCredentialType="Windows" protectionLevel="EncryptAndSign"></transport>
  <message clientCredentialType="Windows" />
</security>

則,客戶端也需要使用同類的協議,如

複製代碼
<bindings>
    <netTcpBinding>
        <binding name="NetTcpBinding_IDataSyncEntry">
            <security mode="None" />
        </binding>
    </netTcpBinding>
</bindings>
複製代碼

或者代碼中

var binding = new NetTcpBinding();
binding.Security = new NetTcpSecurity()
{
    Mode = SecurityMode.None
};

 

P4 契約返回DataTable

問題描述:使用DataTable作爲返回值

解決方案

1) 網上傳說——使用命名的DataTable,即爲DataTable的TableName賦一個名稱(試了一下,不行);

2) 傳遞DataSet可以。

複製代碼
public System.Data.DataSet TestDataTable()
{
    DataTable dt = new DataTable("result");
    dt.TableName = "navigateData";
    dt.Columns.Add("Name",typeof(string));
    var dr = dt.NewRow();
    dr["Name"] = "pz";
    dt.Rows.Add(dr);

    dr = dt.NewRow();
    dr["Name"] = "pz2";
    dt.Rows.Add(dr);

    var ds = new DataSet();
    ds.Tables.Add(dt);

    return ds;
}
複製代碼

 

P5 使用Channel Factory

問題描述:客戶端可以直接“引用服務”以生成***Client,但是,這不利於修改。

修改了接口之後,沒有辦法及時通知到客戶端,除了“更新服務飲引用”之外。

解決方案:客戶端引用服務接口,並使用Channel Factory進行解耦,則客戶端只依賴接口。

複製代碼
public static DataSync.Interfaces.IDataSyncEntry CreateDataSyncEntryServices()
{
    EndpointAddress addr = new EndpointAddress("net.tcp://75wojoax/WcfWays/DataSyncServiceImpl.svc");
    var binding = new NetTcpBinding();
    binding.Security = new NetTcpSecurity()
    {
        Mode = SecurityMode.None
    };
    var channel = new ChannelFactory<DataSync.Interfaces.IDataSyncEntry>(binding, addr);
    var service = channel.CreateChannel();
    return service;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章