理解WCF中的会话机制
- 在WCF应用程序中,会话将一组消息相互关联,从而形成对话。会话”是在两个终结点之间发送的所有消息的一种相互关系。当某个服务协定指定它需要会话时,该协定会指定所有调用(即,支持调用的基础消息交换)必须是同一对话的一部分。如果某个协定指定它允许使用会话但不要求使用会话,则客户端可以进行连接,并选择建立会话或不建立会话。如果会话结束,然后在同一个通道上发送消息,将会引发异常。
- WCF中的会话机制通过设置服务协定(ServiceContract)上的SessionMode的枚举值来设置服务协定是否要求、允许或拒绝基于会话的绑定。SessionMode的枚举值有以下三种:
- Allowed:允许会话,这是SessionMode的默认值。也就是说在服务协定上没有采用SessionMode说明时,我们的服务都是采用的允许会话机制。这种机制说明如果客户端将基于会话的绑定用于 WCF 服务实现,则服务将建立并使用提供的会话。
- Required:要求会话,即所有调用(支持调用的基础消息交换)都必须是同一个会话的一部分。
- NotAllowed:禁止会话,即服务端不会与客户端进行消息交换。
影响WCF中的会话机制其他属性机制
- 虽然可以设置SessionMode的值来控制会话,但是基于会话的绑定支持服务对象与特定会话的默认关联,例如:
- 设置了SessionMode的值为Required,当采用的绑定为BasicHttpBinding,因为BasicHttpBinding不支持会话,所以程序还是报错。
- 对于WSHttpBinding和WS2007HttpBinding,如果我们将安全模式设置为None(关闭安全会话)并且关闭可靠会话,他们也无法提供会话支持。
- 对于NetTcpBinding和NetNamedPipeBinding来说,由于其传输类型本身具有支持会话的特性,所以采用了这两种绑定类型的终结点服务协定的会话模式不能设置为NotAllowed,即使关闭了安全会话和可靠会话也不行。
- WCF 提供下列类型的基于会话的应用程序行为:
- System.ServiceModel.Channels.SecurityBindingElement 支持基于安全的会话,其中,两个通信端采用统一的安全对话。例如:System.ServiceModel.WSHttpBinding 绑定(包含对安全会话和可靠会话的支持)默认情况下只使用对消息进行加密和数字签名的安全会话。
- System.ServiceModel.NetTcpBinding 绑定支持基于 TCP/IP 的会话,以确保所有消息都由套接字级别的连接进行关联。
- System.ServiceModel.Channels.ReliableSessionBindingElement 元素实现 WS-ReliableMessaging 规范,并提供对可靠会话的支持。在可靠会话中,可以配置消息以按顺序传递并且只传递一次,从而使消息在对话期间即使经过多个节点也可以确保保密性。
- System.ServiceModel.NetMsmqBinding 绑定提供 MSMQ 数据报会话
- 如果使用 WCF 中的默认实例化行为,则通过同一服务实例来处理 WCF 客户端对象之间的所有调用。因此,在应用程序级别上,可以将会话视为启用与本地调用行为相似的应用程序行为。只要使用默认的服务实例行为,会话就会在客户端和服务之间启用一个相似的行为。如果服务协定需要或支持会话,则通过设置 IsInitiating 和 IsTerminating 属性,可以将一个或多个协定操作标记为启动或终止会话。参考WCF初探-15:WCF操作协定
WCF中的会话与ASP.NET中的会话
- WCF 会话具有下列主要概念性功能:
- 它们由调用应用程序显式启动和终止。
- 会话期间传递的消息按照接收消息的顺序进行处理。
- 会话将一组消息相互关联,从而形成对话。该关联的含义是抽象的。例如,一个基于会话的通道可能会根据共享网络连接来关联消息,而另一个基于会话的通道可能会根据消息正文中的共享标记来关联消息。可以从会话派生的功能取决于关联的性质。
- 不存在与 WCF 会话相关联的常规数据存储区。
- ASP.NET 中的会话由 System.Web.SessionState.HttpSessionState 类提供功能,具有以下特点:
- ASP.NET 会话总是由服务器启动。
- ASP.NET 会话原本是无序的。
- ASP.NET 会话提供了一种跨请求的常规数据存储机制。
WCF中的使用会话示例说明
- 解决方案如下:
- 工程结构说明如下:
- 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(); } } } }