• 风尘浪子 WCF揭秘——可靠性会话功能


    一、可靠性会话

    Windows Communication Foundation (WCF) 可靠性会话是一个如 WS-ReliableMessaging 协议所定义的 SOAP 可靠消息传递的实现。它在绑定层保证消息只会被传送一次,并能确定消息之间的传输顺序。它的特性在于保证了传输过程中消息不会丢失或者错位,在连接掉线的 时候,它会重新连接服务器,连接次数可在配置文件中设定,当在连接失败的时候,能自动释放对话所占用的资源。

    系统有多个绑定支持可靠性会话功能:wsHttpBinding、wsDualHttpBinding、wsFederationBinding、 netTcpBinding、netNamedPipesBinding。其中wsHttpBinding、wsFederationBinding、 netTcpBinding在默认情况下可靠性会话功能是关闭。而wsDualHttpBinding、netNamedPipesBinding则默认 支持可靠性功能。

    二、开发实例

    可靠性会话功能可以通过代码绑定,也可以通过config配置统一绑定,值得注意的是服务器端要与客户端的配置必须保持一致,避免出现冲突。下面以 netTcpBinding契约为例子,说明一下可靠性会话的功能。首先建立数据契约Person,和服务契约PersonService,客户端通过 GetPerson方法获取Person对象。

    • 服务器端
     1 namespace Pro.Model
    2 {
    3 //建立数据契约
    4 [DataContract]
    5 public class Person
    6 {
    7 [DataMember]
    8 public int ID
    9 {
    10 get;
    11 set;
    12 }
    13
    14 [DataMember]
    15 public string Name
    16 {
    17 get;
    18 set;
    19 }
    20
    21 [DataMember]
    22 public int Age
    23 {
    24 get;
    25 set;
    26 }
    27 }
    28 }
    29
    30 namespace Pro.Service
    31 {
    32 // 建立服务契约接口“IPersonService”。
    33 [ServiceContract]
    34 public interface IPersonService
    35 {
    36 [OperationContract]
    37 Person GetPerson();
    38 }
    39
    40 // 实现服务契约“PersonService”。
    41 [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
    42 public class PersonService : IPersonService
    43 {
    44 public Person GetPerson()
    45 {
    46 Person person = new Person();
    47 person.ID = 0;
    48 person.Name = "Leslie";
    49 person.Age = 31;
    50
    51 return person;
    52 }
    53 }
    54
    55 class Program
    56 {
    57 //启动服务
    58 static void Main(string[] args)
    59 {
    60 Console.WriteLine("Service star!");
    61 ServiceHost host1 = new ServiceHost(typeof(PersonService));
    62 host1.Open();
    63 Console.ReadKey();
    64 host1.Close();
    65 }
    66 }
    67 }

    添加config配置文件,加入 reliableSession 配置,包含以下属性

    1.enable 

    返回值为bool类型,代表是否打开可靠性功能。

    2.inactivityTimeout 

    返回值为TimeSpan类型,代表闲置超时时间,默认值为10分钟,如果客户端已经建立起服务对象,在超过此时间内没有重新调用这些对象,系统将 发送提示信息: “通信对象 System.ServiceModel.Channels.ServiceChannel 无法用于通信,因为其处于‘出错’状态。”。

    3.ordered

    返回值为bool类型,代表是否开启“有序性”性功能,如果开启此功能,代表消息将按顺序传送。

    4.maxPendingChannels

    返回值为int 类型,代表最大等候信道,默认值为4。

    5.maxRetryCount

    返回值为int 类型,表示最大重复发送次数,默认值为8,最大值为20。如果因断线等原因连接失败,客户端重试次数超过此最大值,系统将发出错误提示。

    6.flowControlEnabled

    返回值为bool类型,默认值为true,代表是否启动流量控制器。启动后,当接收方的传输数据缓冲区已满时,发送方将延迟发送信息。

    7.acknowledgementInterval

    返回值为TimeSpan类型,默认值为00:00:00.2(即0.2秒),代表接收方在接收信息之前所需要的等待时间。

    8.maxTransferWindowSize

    返回值为int类型,默认值为8,用于控制数据缓冲区数量。

     1 <configuration>
    2 <system.serviceModel>
    3 <behaviors>
    4 <serviceBehaviors>
    5 <behavior name="">
    6 <serviceMetadata httpGetEnabled="false" />
    7 <serviceDebug includeExceptionDetailInFaults="true" />
    8 </behavior>
    9 </serviceBehaviors>
    10 </behaviors>
    11
    12 <bindings>
    13 <netTcpBinding>
    14 <binding name="defaultNetTcpBinding">
    15 <!--打开可靠性会话功能,把过期时间配置为10秒-->
    16 <reliableSession enabled="true" inactivityTimeout="00:00:10"/>
    17 </binding>
    18 </netTcpBinding>
    19 </bindings>
    20
    21 <services>
    22 <service name="Pro.Service.PersonService">
    23 <!--绑定defaultNetTcpBinding-->
    24 <endpoint address="" bindingConfiguration="defaultNetTcpBinding" binding="netTcpBinding" contract="Pro.Service.IPersonService">
    25 <identity>
    26 <dns value="localhost" />
    27 </identity>
    28 </endpoint>
    29 <endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange" />
    30 <host>
    31 <baseAddresses>
    32 <add baseAddress="net.Tcp://localhost:6000/Pro.Service/PersonService/" />
    33 </baseAddresses>
    34 </host>
    35 </service>
    36 </services>
    37 </system.serviceModel>
    38 </configuration>

    在以上例子中,只在netTcpBincding绑定中加入了enable与inactivityTimeout两个最常用的功能,其意义只在于打 开可靠性会话功能,把超时时间设置为10秒(定制10秒的超时时间,其用意是在于测试在10秒后再次调用服务对象,对象是否会抛出错误提示)。

    • 客户端

    新建一个网站项目,添加对PersonService服务的引用,在页面加入一个Label控件与一个Button控件,在Button的onClick方法调用PersonService服务。

    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
    <title></title>
    <script type="text/C#" runat="server">
    protected void btn1_Click(object sender, EventArgs e)
    {
    //注意在调用完成后把服务销毁
    using (PersonService.PersonServiceClient personService = new PersonService.PersonServiceClient())
    {
    Pro.Model.Person person
    = personService.GetPerson();
    Label1.Text
    = person.Name;
    }
    }
    </script>
    </head>
    <body>
    <form id="form1" runat="server">
    <div>
    <asp:Label ID="Label1" runat="server"></asp:Label>
    <asp:Button ID="btn1" runat="server" Text="Button" OnClick="btn1_Click"/>
    </div>
    </form>
    </body>
    </html>

    配置客户端文件,打开可靠性会话功能,注意把超时时间设置为10秒,与服务器的配置同步。在常用的服务处理页面,使用单体模式或者静态对象,在一定 程序上可以减少服务器的负荷,提高效率。值得注意的是,如果使用单体模式,当服务启动10秒后,如果并未被再次调用,那下次调用时,系统将显示错误信息: “通信对象 System.ServiceModel.Channels.ServiceChannel 无法用于通信,因为其处于‘出错’状态”。所以,在配置“超时时间”时,应该注意控制时间的长短。

    为了避免出现以上错误,在下建议在调用不经常使用的服务之时,应该把服务对象及时销毁,下次调用时重新建立一个服务对象。(可参考“注意事项”)

     1 <configuration>
    2 <system.web>
    3 <compilation debug="true" targetFramework="4.0"/>
    4 </system.web>
    5 <system.serviceModel>
    6 <bindings>
    7 <netTcpBinding>
    8 <binding name="NetTcpBinding_IPersonService" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00"
    sendTimeout
    ="00:01:00" transactionFlow="false" transferMode="Buffered" transactionProtocol="OleTransactions"
    hostNameComparisonMode
    ="StrongWildcard" listenBacklog="10" maxBufferPoolSize="524288" maxBufferSize="65536"
    maxConnections
    ="10" maxReceivedMessageSize="65536">
    9 <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384"/>
    10 <!--启动可靠性会话,把过期时间设置为10秒-->
    11 <reliableSession inactivityTimeout="00:00:10" enabled="true"/>
    12 <security mode="Transport">
    13 <transport clientCredentialType="Windows" protectionLevel="EncryptAndSign"/>
    14 <message clientCredentialType="Windows"/>
    15 </security>
    16 </binding>
    17 </netTcpBinding>
    18 </bindings>
    19 <client>
    20 <endpoint address="net.tcp://localhost:6000/Pro.Service/PersonService/" binding="netTcpBinding"
    bindingConfiguration
    ="NetTcpBinding_IPersonService" contract="PersonService.IPersonService" name="NetTcpBinding_IPersonService">
    21 <identity>
    22 <dns value="localhost"/>
    23 </identity>
    24 </endpoint>
    25 </client>
    26 </system.serviceModel>
    27 </configuration>

    三、注意事项

    值得注意的一点是,在某些不常用到的页面中(比如在Login登录页面),客户往往在长时间内只调用一次服务,所以应该注意对服务对象进行及时销毁,否则客户再次登录时就会出来错误。

     1 <html xmlns="http://www.w3.org/1999/xhtml">
    2 <head runat="server">
    3 <title></title>
    4 <script type="text/C#" runat="server">
    5 static PersonService.PersonServiceClient personService = new PersonService.PersonServiceClient();
    6 //只在页面初次调用时,personService才会被新建,如果超过限时没有被再次调用,就会出现错误
    7
    8 protected void btn1_Click(object sender, EventArgs e)
    9 {
    10 Pro.Model.Person person = personService.GetPerson();
    11 Label1.Text = person.Name;
    12 }
    13 </script>
    14 </head>
    15 <body>
    16 <form id="form1" runat="server">
    17 <div>
    18 <asp:Label ID="Label1" runat="server"></asp:Label>
    19 <asp:Button ID="btn1" runat="server" Text="Button" OnClick="btn1_Click"/>
    20 </div>
    21 </form>
    22 </body>
    23 </html>

    相关文章

    简单的WCF开发实例

    使用AJAX+WCF进行页面开发

    共享数据契约

    可靠性会话功能

    转自 http://www.cnblogs.com/leslies2/archive/2011/08/08/2129422.html

  • 相关阅读:
    【并查集】bzoj1015 [JSOI2008]星球大战starwar
    【二分】bzoj2083 [Poi2010]Intelligence test
    【分块答案】【最小生成树】【kruscal】bzoj1196 [HNOI2006]公路修建问题
    【莫队算法】【权值分块】bzoj3809 Gty的二逼妹子序列
    【莫队算法】【权值分块】bzoj3236 [Ahoi2013]作业
    【分块答案】【最小割】bzoj1532 [POI2005]Kos-Dicing
    【费用流】bzoj3280 小R的烦恼
    【最小路径覆盖】【二分图】【最大流】【Dinic】bzoj2150 部落战争
    【枚举】【二分答案】【分块答案】【BFS】【最大流】【Dinic】bzoj1189 [HNOI2007]紧急疏散evacuate
    【最短路】【spfa】【最小割】【Dinic】bzoj1266 [AHOI2006]上学路线route
  • 原文地址:https://www.cnblogs.com/sunjie9606/p/2131680.html
Copyright © 2020-2023  润新知