zoukankan      html  css  js  c++  java
  • WCF 实例模式和对象生命周期

     1、WCF 几种服务对象实例创建模式

    wcf中有三种服务对象实例创建模式:PerCall、PerSession、Single.(具体在哪里设置,最后例子中有很好的阐述)

    2、几种模式下服务对象实例的生命周期(这里暂不考虑Mep)

     PerCall模式

      PerCall模式工作流程如下

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

      示例代码展示

      服务契约代码如下:

     

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.ServiceModel;

    namespace Contract
    {
    [ServiceContract(Name="CalculatorService",Namespace="http://www/gxs.com")]
    public interface ICalculator:IDisposable
    {
    [OperationContract(Name = "CalculatorAdd")]
    double Add(double x, double y);
    [OperationContract(Name = "CalculatorSubtract")]
    double Subtract(double x, double y);
    }
    }

    服务代码如下:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Contract;
    using System.ServiceModel;

    namespace Service
    {
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
    public class CalculatorPerCall:ICalculator
    {
    public CalculatorPerCall()
    {
    Console.WriteLine("Create a new instance!!!");
    }
    public double Add(double x, double y)
    {
    Console.WriteLine("Call [Add] Method");
    return x + y;
    }
    public double Subtract(double x, double y)
    {
    Console.WriteLine("Call [Subtract] Method");
    return x - y;
    }
    public void Dispose()
    {
    Console.WriteLine("The instance has been disposed!!!");
    }
    }
    }

     

    服务端宿主代码如下:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.ServiceModel;
    using Contract;
    using Service;
    using System.ServiceModel.Description;

    namespace Hosting
    {
    class Program
    {
    static void Main(string[] args)
    {
    using (ServiceHost host = new ServiceHost(typeof(CalculatorPerCall)))
    {
    host.AddServiceEndpoint(typeof(ICalculator), new WSHttpBinding(), "http://127.0.0.1:8089/CalculatorService");
    //ServiceMetadataBehavior:控制服务元数据和相关信息的发布
    if (host.Description.Behaviors.Find<ServiceMetadataBehavior>() == null)
    {
    ServiceMetadataBehavior behavior = new ServiceMetadataBehavior();
    behavior.HttpGetEnabled = true;
    behavior.HttpGetUrl = new Uri("http://127.0.0.1:8089/CalculatorService/metadata");
    host.Description.Behaviors.Add(behavior);
    }
    host.Opened += new EventHandler(host_Opened);
    host.Open();
    Console.Read();
    }
    }

    static void host_Opened(object sender, EventArgs e)
    {
    Console.WriteLine("计算机服务已经被打开了......");
    }
    }
    }



    客户端代码如下:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;

    namespace WcfLifeCycle.Client
    {
    /// <summary>
    /// wcf实例模型
    /// </summary>
    public class ClientCalculator
    {
    public static void Main(string[] args)
    {
    CalculatorServiceClient proxy1 = new CalculatorServiceClient();
    Console.WriteLine("proxy1 Call [Add] method");
    proxy1.CalculatorAdd(12d, 13d);
    Console.WriteLine("proxy1 Call [Add] method");
    proxy1.CalculatorAdd(12d, 13d);
    Console.WriteLine("proxy1 Call [Add] method");
    proxy1.CalculatorAdd(12d, 13d);
    Console.WriteLine("******************************************");
    CalculatorServiceClient proxy2= new CalculatorServiceClient();
    Console.WriteLine("proxy2 Call [Add] method");
    proxy2.CalculatorAdd(12d, 13d);
    Console.WriteLine("proxy2 Call [Add] method");
    proxy2.CalculatorAdd(12d, 13d);
    Console.WriteLine("proxy2 Call [Add] method");
    proxy2.CalculatorAdd(12d, 13d);
    Console.Read();
    }
    }
    }

     结果示例图

     服务端:

    客户端

    小结:Percall模式,客户端每次发出请求后,服务端都会生成一个实例响应,响应完毕后自行销毁。

     PerSession模式

    PerSession模式工作的流程如下:

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

    示例代码展示

      服务契约代码如下:

    View Code
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.ServiceModel;

    namespace Contract
    {
    [ServiceContract(Name="CalculatorService",Namespace="http://www/gxs.com")]
    public interface ICalculator:IDisposable
    {
    [OperationContract(Name = "CalculatorAdd")]
    double Add(double x, double y);
    [OperationContract(Name = "CalculatorSubtract")]
    double Subtract(double x, double y);
    }
    }

    服务代码如下:

    View Code
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Contract;
    using System.ServiceModel;

    namespace Service
    {
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
    public class CalculatorPerSession : ICalculator
    {
    public CalculatorPerSession()
    {
    Console.WriteLine("Create a new instance!!!");
    }
    public double Add(double x, double y)
    {
    Console.WriteLine("Call [Add] Method");
    return x + y;
    }
    public double Subtract(double x, double y)
    {
    Console.WriteLine("Call [Subtract] Method");
    return x - y;
    }
    public void Dispose()
    {
    Console.WriteLine("The instance has been disposed!!!");
    }
    }
    }


    服务端宿主代码

    View Code
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.ServiceModel;
    using Contract;
    using Service;
    using System.ServiceModel.Description;

    namespace Hosting
    {
    class Program
    {
    static void Main(string[] args)
    {
    using (ServiceHost host = new ServiceHost(typeof(CalculatorPerSession)))
    {
    host.AddServiceEndpoint(typeof(ICalculator), new WSHttpBinding(), "http://127.0.0.1:8089/CalculatorService");
    //ServiceMetadataBehavior:控制服务元数据和相关信息的发布
    if (host.Description.Behaviors.Find<ServiceMetadataBehavior>() == null)
    {
    ServiceMetadataBehavior behavior = new ServiceMetadataBehavior();
    behavior.HttpGetEnabled = true;
    behavior.HttpGetUrl = new Uri("http://127.0.0.1:8089/CalculatorService/metadata");
    host.Description.Behaviors.Add(behavior);
    }
    host.Opened += new EventHandler(host_Opened);
    host.Open();
    Console.Read();
    }
    }
    static void host_Opened(object sender, EventArgs e)
    {
    Console.WriteLine("计算机服务已经被打开了......");
    }
    }
    }


    客户端代码如下:

    View Code
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;

    namespace WcfLifeCycle.Client
    {
    /// <summary>
    /// wcf实例模型
    /// </summary>
    public class ClientCalculator
    {
    public static void Main(string[] args)
    {
    CalculatorServiceClient proxy1 = new CalculatorServiceClient();
    Console.WriteLine("proxy1 Call [Add] method");
    proxy1.CalculatorAdd(12d, 13d);
    Console.WriteLine("proxy1 Call [Add] method");
    proxy1.CalculatorAdd(12d, 13d);
    Console.WriteLine("proxy1 Call [Add] method");
    proxy1.CalculatorAdd(12d, 13d);
    Console.WriteLine("******************************************");
    CalculatorServiceClient proxy2= new CalculatorServiceClient();
    Console.WriteLine("proxy2 Call [Add] method");
    proxy2.CalculatorAdd(12d, 13d);
    Console.WriteLine("proxy2 Call [Add] method");
    proxy2.CalculatorAdd(12d, 13d);
    Console.WriteLine("proxy2 Call [Add] method");
    proxy2.CalculatorAdd(12d, 13d);
    Console.Read();
    }
    }
    }


    结果实例图

    服务端

    客户端

    小结:PerSession模式,proxy与服务实例对应。不同的proxy有不同的服务实例。

    Single模式

    Single模式的工作流程如下:

    • 服务端启动,同时创建服务对象
    • 客户端通过代理调用契约操作
    • 第一步中创建的服务对象接受请求 ,并执行操作,进行必要的应答
    • 第一步创建的服务对象将一直保留
    • 服务关闭,第一步创建的对象销毁

    示例代码展示:

    服务契约代码

     

    View Code
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.ServiceModel;

    namespace Contract
    {
    [ServiceContract(Name="CalculatorService",Namespace="http://www/gxs.com")]
    public interface ICalculator:IDisposable
    {
    [OperationContract(Name = "CalculatorAdd")]
    double Add(double x, double y);
    [OperationContract(Name = "CalculatorSubtract")]
    double Subtract(double x, double y);
    }
    }

     
    服务代码

    View Code
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Contract;
    using System.ServiceModel;

    namespace Service
    {
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
    public class CalculatorPerSingle : ICalculator
    {
    public CalculatorPerSingle()
    {
    Console.WriteLine("Create a new instance!!!");
    }
    public double Add(double x, double y)
    {
    Console.WriteLine("Call [Add] Method");
    return x + y;
    }
    public double Subtract(double x, double y)
    {
    Console.WriteLine("Call [Subtract] Method");
    return x - y;
    }
    public void Dispose()
    {
    Console.WriteLine("The instance has been disposed!!!");
    }
    }
    }

    服务端宿主代码

    View Code
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.ServiceModel;
    using Contract;
    using Service;
    using System.ServiceModel.Description;

    namespace Hosting
    {
    class Program
    {
    static void Main(string[] args)
    {
    using (ServiceHost host = new ServiceHost(typeof(CalculatorPerSingle), new Uri("http://127.0.0.1:8089")))
    {
    host.AddServiceEndpoint(typeof(ICalculator), new WSHttpBinding(), "CalculatorServiceOne");
    host.AddServiceEndpoint(typeof(ICalculator), new WSHttpBinding(), "CalculatorServiceTwo");
    //ServiceMetadataBehavior:控制服务元数据和相关信息的发布
    if (host.Description.Behaviors.Find<ServiceMetadataBehavior>() == null)
    {
    ServiceMetadataBehavior behavior = new ServiceMetadataBehavior();
    behavior.HttpGetEnabled = true;
    behavior.HttpGetUrl = new Uri("http://127.0.0.1:8089/CalculatorService/metadata");
    host.Description.Behaviors.Add(behavior);
    }
    host.Opened += new EventHandler(host_Opened);
    host.Open();
    Console.Read();
    }
    }
    static void host_Opened(object sender, EventArgs e)
    {
    Console.WriteLine("计算机服务已经被打开了......");
    }
    }
    }


    客户端一代码

    View Code
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;

    namespace WcfLifeCycle.Client
    {
    /// <summary>
    /// wcf实例模型
    /// </summary>
    public class ClientOneCalculator
    {
    public static void Main(string[] args)
    {
    CalculatorServiceClient proxy1 = new CalculatorServiceClient("WSHttpBinding_CalculatorService");
    Console.WriteLine("I am EndPointOne");
    Console.WriteLine("proxy1 Call [Add] method");
    proxy1.CalculatorAdd(12d, 13d);
    Console.WriteLine("proxy1 Call [Add] method");
    proxy1.CalculatorAdd(12d, 13d);
    Console.WriteLine("proxy1 Call [Add] method");
    proxy1.CalculatorAdd(12d, 13d);
    proxy1.Close();
    Console.Read();
    }
    }
    }

    客户端一配置文件app.config

    View Code
    <?xml version="1.0"?>
    <configuration>
    <system.serviceModel>
    <bindings>
    <wsHttpBinding>
    <binding name="WSHttpBinding_CalculatorService" 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>
    <binding name="WSHttpBinding_CalculatorService1" 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>
    </wsHttpBinding>
    </bindings>
    <client>
    <endpoint address="http://127.0.0.1:8089/CalculatorServiceOne"
    binding
    ="wsHttpBinding" bindingConfiguration="WSHttpBinding_CalculatorService"
    contract
    ="Client.CalculatorService" name="WSHttpBinding_CalculatorService">
    <identity>
    <userPrincipalName value="guxiaoshi-PC\guxiaoshi" />
    </identity>
    </endpoint>
    <endpoint address="http://127.0.0.1:8089/CalculatorServiceTwo"
    binding
    ="wsHttpBinding" bindingConfiguration="WSHttpBinding_CalculatorService1"
    contract
    ="Client.CalculatorService" name="WSHttpBinding_CalculatorService1">
    <identity>
    <userPrincipalName value="guxiaoshi-PC\guxiaoshi" />
    </identity>
    </endpoint>
    </client>
    </system.serviceModel>
    <startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/></startup></configuration>

    客户端二代码

    View Code
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using ClientTwo.Client;

    namespace ClientTwo
    {
    class ClientTwoCalculator
    {
    static void Main(string[] args)
    {
    CalculatorServiceClient proxy1 = new CalculatorServiceClient("WSHttpBinding_CalculatorService1");
    Console.WriteLine("I am EndPointTwo");
    Console.WriteLine("proxy1 Call [Add] method");
    proxy1.CalculatorAdd(12d, 13d);
    Console.WriteLine("proxy1 Call [Add] method");
    proxy1.CalculatorAdd(12d, 13d);
    Console.WriteLine("proxy1 Call [Add] method");
    proxy1.CalculatorAdd(12d, 13d);
    proxy1.Close();
    Console.Read();
    }
    }
    }

    客户端二配置文件app.config

    View Code
    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
    <system.serviceModel>
    <bindings>
    <wsHttpBinding>
    <binding name="WSHttpBinding_CalculatorService" 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>
    <binding name="WSHttpBinding_CalculatorService1" 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>
    </wsHttpBinding>
    </bindings>
    <client>
    <endpoint address="http://127.0.0.1:8089/CalculatorServiceOne"
    binding
    ="wsHttpBinding" bindingConfiguration="WSHttpBinding_CalculatorService"
    contract
    ="Client.CalculatorService" name="WSHttpBinding_CalculatorService">
    <identity>
    <userPrincipalName value="guxiaoshi-PC\guxiaoshi" />
    </identity>
    </endpoint>
    <endpoint address="http://127.0.0.1:8089/CalculatorServiceTwo"
    binding
    ="wsHttpBinding" bindingConfiguration="WSHttpBinding_CalculatorService1"
    contract
    ="Client.CalculatorService" name="WSHttpBinding_CalculatorService1">
    <identity>
    <userPrincipalName value="guxiaoshi-PC\guxiaoshi" />
    </identity>
    </endpoint>
    </client>
    </system.serviceModel>
    </configuration>

    结果实例图

    服务端

    客户端一

    客户端二

    小结:服务端自始至终只有一个实例与客户端进行消息的交换。

    总结:上文是对服务对象实例生命周期的介绍.Percall:新的请求产生新的服务对象与之交换信息,服务对象自行销毁;PerSession:相同的客户端由同一个服务对象与之交换信息(这里的客户端指proxy);Single:服务端只有一个服务实例,服务打开时服务实例就会被创建。

  • 相关阅读:
    某个牛人做WINDOWS系统文件详解
    常用ASP脚本程序集锦
    LINUX基础:文件安全与权限
    proftpd+mysql+quota
    apache2.0.49tomcat5.0.19jk2建立virtualHost
    URL Redirection(转) Anny
    顶级域名后缀列表(转) Anny
    \u4E00\u9FA5意义 Anny
    How to POST Form Data Using Ruby(转) Anny
    How to get rid of 'Enter password to unlock your login keyring' in Ubuntu(转) Anny
  • 原文地址:https://www.cnblogs.com/smallstone/p/2277194.html
Copyright © 2011-2022 走看看