WCF 采用net.tcp协议实践

来源:互联网 发布:淘宝首页轮播图尺寸 编辑:程序博客网 时间:2024/06/07 03:59

与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;}
1 0
原创粉丝点击