WCF初探-26:WCF中的会话

理解WCF中的会话机制

  • 在WCF应用程序中,会话将一组消息相互关联,从而形成对话。会话”是在两个终结点之间发送的所有消息的一种相互关系。当某个服务协定指定它需要会话时,该协定会指定所有调用(即,支持调用的基础消息交换)必须是同一对话的一部分。如果某个协定指定它允许使用会话但不要求使用会话,则客户端可以进行连接,并选择建立会话或不建立会话。如果会话结束,然后在同一个通道上发送消息,将会引发异常。

  

  • WCF中的会话机制通过设置服务协定(ServiceContract)上的SessionMode的枚举值来设置服务协定是否要求、允许或拒绝基于会话的绑定。SessionMode的枚举值有以下三种:
  1. Allowed:允许会话,这是SessionMode的默认值。也就是说在服务协定上没有采用SessionMode说明时,我们的服务都是采用的允许会话机制。这种机制说明如果客户端将基于会话的绑定用于 WCF 服务实现,则服务将建立并使用提供的会话。
  2. Required:要求会话,即所有调用(支持调用的基础消息交换)都必须是同一个会话的一部分。
  3. NotAllowed:禁止会话,即服务端不会与客户端进行消息交换。

影响WCF中的会话机制其他属性机制

  • 虽然可以设置SessionMode的值来控制会话,但是基于会话的绑定支持服务对象与特定会话的默认关联,例如:
  1. 设置了SessionMode的值为Required,当采用的绑定为BasicHttpBinding,因为BasicHttpBinding不支持会话,所以程序还是报错。
  2. 对于WSHttpBinding和WS2007HttpBinding,如果我们将安全模式设置为None(关闭安全会话)并且关闭可靠会话,他们也无法提供会话支持。
  3. 对于NetTcpBinding和NetNamedPipeBinding来说,由于其传输类型本身具有支持会话的特性,所以采用了这两种绑定类型的终结点服务协定的会话模式不能设置为NotAllowed,即使关闭了安全会话和可靠会话也不行。
  • WCF 提供下列类型的基于会话的应用程序行为:
  1. System.ServiceModel.Channels.SecurityBindingElement 支持基于安全的会话,其中,两个通信端采用统一的安全对话。例如:System.ServiceModel.WSHttpBinding 绑定(包含对安全会话和可靠会话的支持)默认情况下只使用对消息进行加密和数字签名的安全会话。
  2. System.ServiceModel.NetTcpBinding 绑定支持基于 TCP/IP 的会话,以确保所有消息都由套接字级别的连接进行关联。
  3. System.ServiceModel.Channels.ReliableSessionBindingElement 元素实现 WS-ReliableMessaging 规范,并提供对可靠会话的支持。在可靠会话中,可以配置消息以按顺序传递并且只传递一次,从而使消息在对话期间即使经过多个节点也可以确保保密性。
  4. System.ServiceModel.NetMsmqBinding 绑定提供 MSMQ 数据报会话
  • 如果使用 WCF 中的默认实例化行为,则通过同一服务实例来处理 WCF 客户端对象之间的所有调用。因此,在应用程序级别上,可以将会话视为启用与本地调用行为相似的应用程序行为。只要使用默认的服务实例行为,会话就会在客户端和服务之间启用一个相似的行为。如果服务协定需要或支持会话,则通过设置 IsInitiating 和 IsTerminating 属性,可以将一个或多个协定操作标记为启动或终止会话。参考WCF初探-15:WCF操作协定

WCF中的会话与ASP.NET中的会话

  • WCF 会话具有下列主要概念性功能:
  1. 它们由调用应用程序显式启动和终止。
  2. 会话期间传递的消息按照接收消息的顺序进行处理。
  3. 会话将一组消息相互关联,从而形成对话。该关联的含义是抽象的。例如,一个基于会话的通道可能会根据共享网络连接来关联消息,而另一个基于会话的通道可能会根据消息正文中的共享标记来关联消息。可以从会话派生的功能取决于关联的性质。
  4. 不存在与 WCF 会话相关联的常规数据存储区。
  • ASP.NET 中的会话由 System.Web.SessionState.HttpSessionState 类提供功能,具有以下特点:
  1. ASP.NET 会话总是由服务器启动。
  2. ASP.NET 会话原本是无序的。
  3. ASP.NET 会话提供了一种跨请求的常规数据存储机制。

WCF中的使用会话示例说明

  • 解决方案如下:

  

  • 工程结构说明如下:
  1. Service:类库程序,WCF服务端应用程序。服务协定中我们将SessionMode的值设置为Required,也就是服务必须要求会话。操作协定中将MethodOne的IsTerminating设置为true,也就是说在客户端调用MethodOne后就会关闭会话(注意:设置了IsTerminating为true的方法是在调用后,服务的会话才会关闭,所以操作协定MethodOne在客户端的调用是成功的)。ISampleMethod.cs的代码如下:
using System.ServiceModel;

namespace Service
{
    [ServiceContract(SessionMode=SessionMode.Required)]
    public interface ISampleMethod
    {
        [OperationContract(IsTerminating=true)]
        string MethodOne(string msg);

        [OperationContract]
        string MethodTwo(string msg);
    }
}

  SampleMethod.cs的代码如下:

namespace Service
{
    public class SampleMethod:ISampleMethod
    {
        public string MethodOne(string msg)
        {
            return "You called MethodOne return message is: " + msg;
        }

        public string MethodTwo(string msg)
        {
            return "You called MethodTwo return message is: " + msg;
        }
    }
}

  2.  Host:控制台应用程序,服务承载程序。添加对程序集Service的引用,完成以下代码,寄宿服务。Program.cs代码如下:

  

using System;
using System.ServiceModel;
using Service;

namespace Host
{
    class Program
    {
        static void Main(string[] args)
        {
            using (ServiceHost host = new ServiceHost(typeof(SampleMethod)))
            {
                host.Opened += delegate { Console.WriteLine("服务已经启动,按任意键终止!"); };
                host.Open();
                Console.Read();
            }
        }
    }
}

  App.config代码如下:

  

<?xml version="1.0"?>
<configuration>
    <system.serviceModel>

        <services>
            <service name="Service.SampleMethod" behaviorConfiguration="mexBehavior">
                <host>
                    <baseAddresses>
                        <add baseAddress="http://localhost:1234/SampleMethod/"/>
                    </baseAddresses>
                </host>
                <endpoint address="" binding="wsHttpBinding" contract="Service.ISampleMethod" />
                <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
            </service>
        </services>

        <behaviors>
            <serviceBehaviors>
                <behavior name="mexBehavior">
                    <serviceMetadata httpGetEnabled="true"/>
                    <serviceDebug includeExceptionDetailInFaults="true"/>
                </behavior>
            </serviceBehaviors>
        </behaviors>
    </system.serviceModel>
</configuration>

  我们通过svcutil.exe工具生成客户端代理类和客户端的配置文件

  svcutil.exe是一个命令行工具,位于路径C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin下,

  我们可以通过命令行运行该工具生成客户端代理类

  在运行中输入cmd打开命令行,输入 cd C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin

  输入svcutil.exe /out:f:\ SampleMethodClient.cs /config:f:\App.config http://localhost:1234/SampleMethod

  

  3.  Client:控制台应用程序,客户端调用程序。将生成的SampleMethodClient.cs和App.config复制到Client的工程目录下,完成客户端调用代码。

    为验证WCF的会话特点,我们将客户端的调用分为以下几种情况:

  • 实例化客户端代理类对象Client1,调用MethodOne和MethodTwo,由于MethodOne的IsTerminating设置为true,所以在客户端Client1调用完MethodOne后会话就会关闭,所以MethodTwo调用不会成功。Client1在调用MethodOne的时候,会话机制会自动启动。由于话期间传递的消息按照接收消息的顺序进行处理,所以在Client1调用MethodOne后再次调用MethodOne也不会成功。即在调用MethodOne方法后的调用都不会成功。参考代码如下:
using System;
namespace Client{
    class Program{
        static void Main(string[] args){
            try{
                SampleMethodClient client1 = new SampleMethodClient();
                Console.WriteLine(client1.MethodOne("MethodOne"));
                Console.WriteLine(client1.MethodTwo("MethodTwo"));
            }       catch (Exception ex){
                Console.WriteLine(ex.Message);
            }
            finally{
                Console.Read();
            }
        }}}

  运行结果如下:

  

  • 实例化客户端代理类对象Client1和Client2,在两个实例化对象中分别调用MethodOne,可以看到调用成功,因为默认的服务实例化模型(InstanceContextMode)采用PerSession,即每个服务实例都各自创建了一个会话通道,当Client1调用MethodOne后会话关闭,但Client2的会话通道并没有关闭,所以还是可以调用MethodOne。在调用MethodOne后两个会话都会关闭,这是由于MethodOne的IsTerminating设置为true的结果。参考代码如下: 
    try
      {
           SampleMethodClient client1 = new SampleMethodClient();
           Console.WriteLine(client1.MethodOne("First Called MethodOne"));

           SampleMethodClient client2 = new SampleMethodClient();
           Console.WriteLine(client2.MethodOne("Second Called MethodOne"));
      }
      catch (Exception ex)
      {
           Console.WriteLine(ex.Message);
      }
      finally
      {
           Console.Read();
      }

  运行结果如下:

  

  • 由于本示例采用的是wsHttpBinding绑定机制,可以把客户端生成的配置文件的可靠会话(reliableSession) enabled设置为false,安全会话(security)的mode设置为none.这样即使服务协定采用了会话支持,但是由于绑定机制的影响,所以会话通道不会建立成功。将客户端配置文件中的
<security mode="Message">
     <transport clientCredentialType="Windows" proxyCredentialType="None" realm="" />
     <message clientCredentialType="Windows" negotiateServiceCredential="true" algorithmSuite="Default" establishSecurityContext="true" />
</security>

  替换为

<security mode="None"/>

  运行结果如下:

  

时间: 2024-12-26 19:12:02

WCF初探-26:WCF中的会话的相关文章

WCF初探-27:WCF中的实例化

理解WCF中的实例化机制 “实例化”是指对用户定义的服务对象以及与其相关的 InstanceContext 对象的生存期的控制.也就是说我们的客户端程序在调用服务端方法时,需要实例化一个服务端代理类对象,实例化就是对这个对象的生命周期的管理(比如:代理服务对象的创建,对象调用服务端方法后需要对其进行的回收处理). 实例化行为(使用 System.ServiceModel.ServiceBehaviorAttribute.InstanceContextMode 属性进行设置)控制如何创建 Inst

WCF初探-28:WCF中的并发

理解WCF中的并发机制 在对WCF并发机制进行理解时,必须对WCF初探-27:WCF中的实例化进行理解,因为WCF中的并发特点是伴随着服务实例上下文实现的.WCF的实例上下文模型可以通过InstanceContext的属性来进行设置,WCF中的并发就是指一个实例上下文处理请求消息的能力,当需要在一个实例上下文中处理多个消息请求时就会产生并发.所以当InstanceContextMode的值为PerSession或Single的时候就会产生并发的情况,这时我们可以通过设置ConcurrencyMo

WCF初探-22:WCF中使用Message类(上)

前言 从我们学习WCF以来,就一直强调WCF是基于消息的通信机制.但是由于WCF给我们做了高级封装,以至于我们在使用WCF的时候很少了解到消息的内部机制.由于WCF的架构的可扩展性,针对一些特殊情况,WCF为我们提供了Message类来深度定制消息结构,以便我们拓展WCF的通信机制. 在之前的文章中,我们针对一些常用的WCF传递数据的方式进行了说明,比如数据协定和消息协定等.他们传递的数据最终都会转化为消息的实例.具体参照:        WCF初探-16:WCF数据协定之基础知识       

重温WCF之WCF中可靠性会话(十四)

1.WCF中可靠性会话在绑定层保证消息只会被传输一次,并且保证消息之间的顺序.当使用TCP(Transmission Control Protocol,传输控制协议)通信时,协议本身保证了可靠性.然而,它只在两点之间的网络包这个层面提供了这样的保证.WCF的可靠性会话特性保证了在传输过程中消息不会丢失.重复或错位.这种保证是消息层面的,而且适用于任何数目节点的通信.另外,使用可靠性会话时,WCF会重连掉线的连接,在重连失败时还会释放会话占用的相关资源.可靠性会话还会通过调整消息的发送频率来缓解网

WCF初探-25:WCF中使用XmlSerializer类

前言 在上一篇WCF序列化和反序列化中,文章介绍了WCF序列化和反序列化的机制,虽然WCF针对序列化提供了默认的DataContractSerializer序列化引擎,但是WCF还支持其他的序列化引擎,那就是XmlSerializer序列化引擎.本文将详细介绍XmlSerializer类在WCF中具体的使用方式. XmlSerializer类概述 XmlSerializer 类不是 WCF 的专用类.ASP.NET Web 服务同样使用该类作为序列化引擎. XmlSerializer 类支持的类

WCF初探-15:WCF操作协定

前言: 在前面的文章中,我们定义服务协定时,在它的操作方法上都会加上OperationContract特性,此特性属于OperationContractAttribute 类,将OperationContract应用于方法,以指示该方法实现作为服务协定(由 ServiceContractAttribute 属性指定)一部分的服务操作.OperationContractAttribute 属性声明方法是服务协定中的操作. 只有具有 OperationContractAttribute 属性的方法可

WCF初探-13:WCF客户端为双工服务创建回调对象

前言: 在WCF初探-5:WCF消息交换模式之双工通讯(Duplex)博文中,我讲解了双工通信服务的一个应用场景,即订阅和发布模式,这一篇,我将通过一个消息发送的例子讲解一下WCF客户端如何为双工服务创建回调对象. 双工服务指定一个回调协定,客户端应用程序必须实现该协定以便提供一个该服务能够根据协定要求调用的回调对象.虽然回调对象不是完整的服务(例如,您无法使用回调对象启动一个通道),但是为了实现和配置,这些回调对象可以被视为一种服务. 双工服务的客户端必须: 实现一个回调协定类. 创建回调协定

WCF初探-14:WCF服务协定

前言: 在前面的文章中,我们定义的服务协定上都会有一个ServiceContract的特性来修饰,这是因为服务契约的实现要靠ServiceContractAttribute 属性定义,然后使用一个或多个类(或接口)方法中的 OperationContractAttribute 属性定义协定的服务操作. 实现服务协定后并将其与WCF 绑定和 EndpointAddress 对象一起使用时,此服务协定将公开以供客户端使用. 公开的信息由 ServiceContractAttribute 表示,其接口

WCF初探-1:认识WCF

1.WCF是什么? WindowsCommunication Foundation(WCF)是由微软发展的一组数据通信的应用程序开发接口,它是.NET框架的一部分,由.NET Framework 3.0开始引入,与Windows Presentation Foundation及 Windows Workflow Foundation并行为新一代Windows操作系统以及WinFX的三个重大应用程序开发类库. 在.NETFramework 2.0以及前版本中,微软发展了Web Service(SO