WCF一步一步往前爬(六)

本文介绍WCF中PerSession工作方式的实现,包括服务端和客户端的代码示例,以及与不同绑定类型的兼容性。重点展示了如何在PerSession模式下使用LifeCycleService服务,包括服务实例的创建、调用方法和会话生命周期。
 wcf中会话模式(PerSession)的应用。

PerSession工作方式:

  • 客户端创建代理对象(Proxy)
  • 客户端第一次调用代理对象的一个契约操作,代理对象将其调用请求传递给服务宿主
  • 宿主程序创建新的服务对象,并执行请求操作,如果有必要,返回客户端应答
  • 客户端再次发出调用操作的请求,宿主会先判断是否已有建立好的会话,如果存在,则不需要再创建新的服务对象,直接使用老对象即可。
  • 在时间达到指定要求或者因一些特殊原因,会话会过期,此时服务对象销毁。

    对于会话模式,basicHttpBinding是不支持的,所以如果是发布到iis,终结点的绑定不能是basicHttpBinding,可以选择netTcpBinding和ws2007HttpBinding

    下面看看例子:

    服务端:

    namespace LifeCycleService
    {
    // 注意: 使用“重构”菜单上的“重命名”命令,可以同时更改代码和配置文件中的接口名“IService”。
    [ServiceContract(SessionMode= SessionMode.Required)]
    public interface ILifeCycleService
    {
    [OperationContract]
    string DoWork();

    [OperationContract]
    string GetInstance();
    }
    }

    namespace LifeCycleService
    {
    // 注意: 使用“重构”菜单上的“重命名”命令,可以同时更改代码、服务和配置文件中的类名“Service”。
    //[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
    //[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
    public class LifeCycleServiceImpl : ILifeCycleService
    {
    // 服务实例的个数
    static int instance;
    int times = 0;

    // 构造函数,初始化callCount,并将服务实例的个数加1
    public LifeCycleServiceImpl()
    {
    instance++;
    System.Diagnostics.Debug.WriteLine("Create a new instance: " + instance.ToString() + "");
    }

    public string GetInstance()
    {
    string outstr = string.Format("Current Instance is {0}", instance);
    return outstr;
    }

    // 被调用的函数,每次被调用callCount加1
    public string DoWork()
    {
    times++;
    string OutStr = string.Format("DoWork() is called by Instance {0}--Times:{1}", OperationContext.Current.SessionId, times);
    return OutStr;
    }
    }
    }

    <%@ ServiceHost Language="C#" Debug="true" Service="LifeCycleService.LifeCycleServiceImpl" CodeBehind="~/App_Code/LifeCycleService.cs" %>

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

    <services>

    <service name="LifeCycleService.LifeCycleServiceImpl">
    <endpoint address="http://lisheng/LifeCycleService/LifeCycleService.svc" binding="ws2007HttpBinding"
    name="LifeCycle_ws2007HttpBinding" contract="LifeCycleService.ILifeCycleService" />

    <endpoint address="net.tcp://lisheng/LifeCycleService/LifeCycleService.svc" binding="netTcpBinding"
    name="LifeCycle_netTcpBinding" contract="LifeCycleService.ILifeCycleService" />
    </service>

    </services>

    <behaviors>
    <serviceBehaviors>
    <behavior>
    <!-- 为避免泄漏元数据信息,请在部署前将以下值设置为 false 并删除上面的元数据终结点 -->
    <serviceMetadata httpGetEnabled="true"/>
    <!-- 要接收故障异常详细信息以进行调试,请将以下值设置为 true。在部署前设置为 false 以避免泄漏异常信息-->
    <serviceDebug includeExceptionDetailInFaults="false"/>
    </behavior>
    </serviceBehaviors>
    </behaviors>

    <serviceHostingEnvironment multipleSiteBindingsEnabled="false">
    <serviceActivations>
    <add relativeAddress="LifeCycleService.svc" service="LifeCycleService.LifeCycleServiceImpl" />
    </serviceActivations>
    </serviceHostingEnvironment>

    </system.serviceModel>
    <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
    </system.webServer>

    </configuration>

    客户端:

    static void Main(string[] args)
    {
    Console.WriteLine("When the service is ready, press any key to countinue!");
    Console.ReadKey(true);


    using (LifeCycleServiceClient client1 = new LifeCycleServiceClient("LifeCycle_netTcpBinding"))
    {
    client1.Open();
    Console.WriteLine(string.Format("=============start: {0}================", client1.GetInstance()));
    for (int i = 1; i < 4; i++)
    {
    Console.WriteLine(client1.DoWork());
    }

    Console.WriteLine(string.Format("=============end: {0}================", client1.GetInstance()));
    }
    Console.WriteLine();


    using (LifeCycleServiceClient client2 = new LifeCycleServiceClient("LifeCycle_ws2007HttpBinding"))
    {
    client2.Open();
    Console.WriteLine(string.Format("=============start: {0}================", client2.GetInstance()));
    for (int i = 1; i < 4; i++)
    {
    Console.WriteLine(client2.DoWork());
    }
    Console.WriteLine(string.Format("=============end: {0}================", client2.GetInstance()));
    }
    Console.ReadKey(true);

    }

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
    <system.serviceModel>
    <bindings>
    <netTcpBinding>
    <binding name="LifeCycle_netTcpBinding" 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">
    <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
    maxBytesPerRead="4096" maxNameTableCharCount="16384" />
    <reliableSession ordered="true" inactivityTimeout="00:10:00"
    enabled="false" />
    <security mode="Transport">
    <transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" />
    <message clientCredentialType="Windows" />
    </security>
    </binding>
    </netTcpBinding>
    <ws2007HttpBinding>
    <binding name="LifeCycle_ws2007HttpBinding" closeTimeout="00:01:00"
    openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
    bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"
    maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
    messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"
    allowCookies="false">
    <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
    maxBytesPerRead="4096" maxNameTableCharCount="16384" />
    <reliableSession ordered="true" inactivityTimeout="00:10:00"
    enabled="false" />
    <security mode="Message">
    <transport clientCredentialType="Windows" proxyCredentialType="None"
    realm="" />
    <message clientCredentialType="Windows" negotiateServiceCredential="true"
    algorithmSuite="Default" />
    </security>
    </binding>
    </ws2007HttpBinding>
    </bindings>
    <client>
    <endpoint address="http://lisheng/LifeCycleService/LifeCycleService.svc"
    binding="ws2007HttpBinding" bindingConfiguration="LifeCycle_ws2007HttpBinding"
    contract="LifeCycleService.ILifeCycleService" name="LifeCycle_ws2007HttpBinding">
    <identity>
    <servicePrincipalName value="host/lisheng" />
    </identity>
    </endpoint>
    <endpoint address="net.tcp://lisheng/LifeCycleService/LifeCycleService.svc"
    binding="netTcpBinding" contract="LifeCycleService.ILifeCycleService"
    name="LifeCycle_netTcpBinding" />
    </client>
    </system.serviceModel>
    </configuration>

    看看另外两种模式工作方式:

    PerCall:

    1. 客户端创建代理对象(Proxy)
    2. 客户端调用代理对象的一个契约操作,代理对象将其传递给服务宿主程序。
    3. 宿主应用程序创建一新的服务契约对象,并且执行请求操作
    4. 在执行完请求操作后,如果要求有应答,那么服务契约会给代理对象一个应答,然后销毁自己(如果实现了IDisposable,则调用Dispose())。

    Single :

    1. 服务端启动,同时创建服务对象
    2. 客户端通过代理调用契约操作
    3. 第一步中创建的服务对象接受请求 ,并执行操作,进行必要的应答
    4. 第一步创建的服务对象将一直保留
    5. 服务关闭,第一步创建的对象销毁
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

leesmn

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值