WCF会话(Session)与实例(Instance)管理
一、理解Session
1.Session的作用:保留Client和Service之间交互的状态,确保Client与Service之间交互唯一性(SessionId),即:多个Client同时访问Service,Service能够区别;
2.ASP.NET Session 与 WCF Session区别:
在WCF中,Session属于Service Contract的范畴,并在Service Contract定义中通过SessionModel参数来实现。WCF中会话具有以下几个重要的特征:
- Session都是由Client端显示启动和终止的。
在WCF中Client通过创建的代理对象来和服务进行交互,在支持Session的默认情况下,Session是和具体的代理对象绑定在一起,当Client通过调用代理对象的某个方法来访问服务时,Session就被初始化,直到代理的关闭,Session则被终止。我们可以通过两种方式来关闭代理:一是调用ICommunicationObject.Close 方法,二是调用ClientBase<TChannel>.Close 方法 。我们也可以通过服务中的某个操作方法来初始化、或者终止Session,可以通过OperationContractAttribute的IsInitiating和IsTerminating参数来指定初始化和终止Session的Operation。
- 在WCF会话期间,传递的消息按照它发送的顺序被接收。
- WCF并没有为Session支持保存相关的状态数据。
而Asp.net中的Session具有以下特性:
- Asp.net的Session总是由服务端启动的,即在服务端进行初始化的。
- Asp.net中的Session是无序的,不能保证请求处理是有序的。
- Asp.net是通过在服务端以某种方式保存State数据来实现对Session的支持,例如保存在Web Server端的内存中。
二、WCF实例管理
对于Client来说,它实际上不能和Service进行直接交互,它只能通过客户端创建的Proxy来间接地和Service进行交互,然而真正的调用而是通过服务实例来进行的。我们把通过Client的调用来创建最终的服务实例过程称作激活,在.NET Remoting中包括Singleton模式、SingleCall模式和客户端激活方式,WCF中也有类似的服务激活方式:单调服务(PerCall)、会话服务(PerSession)和单例服务(Singleton)。
- 单调服务(Percall):为每个客户端请求分配一个新的服务实例。类似.NET Remoting中的SingleCall模式
- 会话服务(Persession):在会话期间,为每次客户端请求共享一个服务实例,类似.NET Remoting中的客户端激活模式。
- 单例服务(Singleton):所有客户端请求都共享一个相同的服务实例,类似于.NET Remoting的Singleton模式。但它的激活方式需要注意一点:当为对于的服务类型进行Host的时候,与之对应的服务实例就被创建出来,之后所有的服务调用都由这个服务实例进行处理。
注意:
1.WCF中服务激活的默认方式是PerSession,但不是所有的Bingding都支持Session,比如BasicHttpBinding就不支持Session。
2.通过在服务契约接口上ServiceContract(SessionMode = 会话模式)来显式设置会话模式,禁用会话模式,可设为:SessionMode.NotAllowed
3.通过在Service实现类上ServiceBehavior(InstanceContextMode=激活方式)来显式设置服务实例激活方式
三、运用WCF 的单例服务(Singleton)及会话模式,实现系统同一时间只能允许同一用户名登录(即:单次登录),代码如下:
1.定义服务契约及创建服务类
using System.ServiceModel; namespace WcfServiceLibrary1
{
[ServiceContract(SessionMode = SessionMode.Required)]
public interface ILogin
{
[OperationContract]
string Login(string username, string password); [OperationContract(IsOneWay=true)]
void Logout();
}
} using System.Collections.Generic;
using System.ServiceModel; namespace WcfServiceLibrary1
{
[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)]
public class LoginService:ILogin
{
private Dictionary<string,string> loginUsers; public LoginService()
{
this.loginUsers = new Dictionary<string, string>();
} public string Login(string username, string password)
{
if (!string.IsNullOrEmpty(username) && password == "")
{
if (!this.loginUsers.ContainsValue(username))
{
this.loginUsers.Add(OperationContext.Current.SessionId,username);
return null;
}
else
{
return string.Format("用户{0}已在其它地方有登录,同一时间不允许同一用户重复登录!", username);
}
}
else
{
return "用户名或密码错误!";
}
} public void Logout()
{
this.loginUsers.Remove(OperationContext.Current.SessionId);
} }
}
2.创建宿主程序
CONFIG配置文件:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<behaviors>
<behavior name="LoginServicemetadatabehavior">
<serviceMetadata httpGetEnabled="true"/>
</behavior>
</behaviors>
<services>
<service name="WcfServiceLibrary1.LoginService" behaviorConfiguration="LoginServicemetadatabehavior">
<endpoint address="" binding="wsHttpBinding" contract="WcfServiceLibrary1.ILogin"></endpoint>
<host>
<baseAddresses>
<add baseAddress="http://127.0.0.1:10900/LoginService"/>
</baseAddresses>
</host>
</service>
</services>
</system.serviceModel>
</configuration>
代码部份:
using System;
using WcfServiceLibrary1;
using System.ServiceModel;
using System.ServiceModel.Description; namespace ConsoleApplicationHost
{
class Program
{
static void Main(string[] args)
{
BuildLoginServiceHostByConfig();
} static void BuildLoginServiceHostByConfig()
{
using (ServiceHost host = new ServiceHost(typeof(LoginService)))
{
host.Opened += (s, e) => { Console.WriteLine("LoginService已经启动,按按回车键终止服务!"); };
host.Open();
Console.ReadLine();
}
}
}
}
3.在客户端程序调用WCF服务
首先添加并引用WCF服务,VS自动生成WCF服务相关的接口与代理类,这里是:LoginClient
然后就可以直接使用LoginClient来调用WCF服务相关方法,代码如下:
using System;
using System.ServiceModel;
using WcfServiceLibrary1; namespace ConsoleApplicationClient
{
class Program
{
static void Main(string[] args)
{
CallLoginService();
Console.WriteLine("按任意键结束。");
Console.Read();
} static void CallLoginService()
{
using (LoginServices.LoginClient proxy = new LoginServices.LoginClient())
{
Console.Write("请输入用户名:");
string input1 = Console.ReadLine();
Console.Write("请输入密码:");
string input2 = Console.ReadLine();
string loginResult = proxy.Login(input1, input2);
if (!string.IsNullOrEmpty(loginResult))
{
Console.WriteLine(loginResult);
return;
} Console.WriteLine("恭喜你,登录成功!");
Console.Write("若需登出,请输入Y:");
string input3 = Console.ReadLine();
if (input3 == "Y")
{
proxy.Logout();
Console.WriteLine("登出成功!");
} }
}
}
}
如果同时打开多个客户端程序,并输入相同的用户名,只要有一个登录成功或登录成功后不登出,其余的均会登录不上,报错!效果如下图示:
![]() |
![]() |
当然也可以利用其它激活方式实现更多功能,在此就不再重述,原理相同!
本文参考与引用了以下作者的文章:
跟我一起学WCF(8)——WCF中Session、实例管理详解
WCF会话(Session)与实例(Instance)管理的更多相关文章
- 跟我一起学WCF(8)——WCF中Session、实例管理详解
一.引言 由前面几篇博文我们知道,WCF是微软基于SOA建立的一套在分布式环境中各个相对独立的应用进行交流(Communication)的框架,它实现了最新的基于WS-*规范.按照SOA的原则,相对独 ...
- 使用SpringSession管理分布式系统的会话Session
在我方供应链项目分布式部署的环境下,需要在统一网关服务中管理访问的Session,即无论访问请求路由到哪一个网关服务环境,使用的都是相同的HttpSession,这样就保证了在用户登录之后,能够使用统 ...
- Oracle 启动实例(instance)、打开数据库
Oracle启动实例(instance).打开数据库 by:授客 QQ:1033553122 启动实例(instance).打开数据库 1.开启sqlplus [laiyu@localhost ~ ...
- [WCF编程]8.服务实例的生命周期
一.服务实例的生命周期概览 我们已经直到,通过显式调用Close方法或等待默认的超时时间到来,都可以释放服务实例.但是,在会话连接里,经常需要按一定顺序调用方法. 二.分步操作 会话契约的操作有时隐含 ...
- WCF服务类的实例模式(本文为转载)
WCF开发时如何选择正确的实例模式(InstanceMode)? 在使用WCF实例模型时,你是否思考过这几个的问题: ”WCF中的实例模式如何正确应用”? ”使用WCF中的实例模式有何原则可以遵循 ...
- MyBatis之会话Session原理
MyBatis 之会话 Session 执行逻辑 1.SQL 会话工厂构建器类 SqlSessionFactoryBuilder 的 build 方法用于构建 SqlSessionFactory 类的 ...
- 简单PHP会话(session)说明
现在程序员愈发的不容易了,想要精通,必然要寻本溯源,这其实与目前泛滥的愈发高级的语言以及众多的框架刚好相反,因为它们在尽可能的掩盖本源使其简单,个人称之为程序员学习悖论. 注:作者接触web开发和ph ...
- PHP之session相关实例教程与经典代码
·php 中cookie和session的用法比较 ·phpmyadmin报错:Cannot start session without errors问题 ·php中cookie与session应用学 ...
- Tensorflow会话Session
转载自: http://blog.csdn.net/Hanging_Gardens/article/details/72784392 https://www.cnblogs.com/hypnus-ly ...
随机推荐
- 将SQL SERVER数据库改成MySql
(www.helpqy.com) 架构在阿里云上,最先想采用SQL SERVER,想大家都是微软家族的嘛.但是发现SQL SERVER需要的配置比较高,需要的银子也比较多,最后在纠结之下换成了MySq ...
- java提高篇(六)-----使用序列化实现对象的拷贝
我们知道在Java中存在这个接口Cloneable,实现该接口的类都会具备被拷贝的能力,同时拷贝是在内存中进行,在性能方面比我们直接通过new生成对象来的快,特别是在大对象的生成上,使得性能的提升非常 ...
- jQuery.width()和jQuery.css('width')的区别
[TOC] 问题描述 使用jQuery修改一个div的宽度时,发现$($0).width('10rem')总是修改成不正确的值,然后使用$($0).css('width', '10rem')时却能正确 ...
- 虚拟化平台cloudstack(8)——从UI开始
UI ucloudstack采用的是前后端分离的架构,就是说前端可以选择使用web.swing甚至其它的界面,都可以. 我们来看cloudstack的UI信息吧,所有的cloudstack的UI都在{ ...
- Springlake-02 权限&文档设置&Role设置&Folder设置&登录
1. 权限 有3个默认的权限用户: 1.System Owner so 管理员权限全部:Type Setup; Group Setup; Form Setup; Role Setup; Share R ...
- MVVM架构~knockoutjs系列之Mapping插件为对象添加ko属性
返回目录 对于一个JS对象来说,如果希望将所有属性进行监视,在之前我们需要一个个对属性添加ko.observable方法,而有了Mapping插件后,它可以帮助我们这件事. 在Mapping出现之前 ...
- Atitit DbServiceV4qb9 数据库查询类库v4 新特性
Atitit DbServiceV4qb9 数据库查询类库v4 新特性 V4新特性 安全特性,屏蔽了executeUpdate,使用v2版 Sql异常转换,特别转换了DuplicateEnt ...
- Atititcmd cli环境变量的调用设置与使用
Atititcmd cli环境变量的调用设置与使用 1.1. Cgi 环境变量的调用设置与使用1 1.2. 环境变量vs 系统变量1 1.3. 环境变量的分类 A.与服务器相关的环境变量B ,与客户 ...
- Atitit.软件与编程语言中的锁机制原理attilax总结
Atitit.软件与编程语言中的锁机制原理attilax总结 1. 用途 (Db,业务数据加锁,并发操作加锁.1 2. 锁得类型 排它锁 "互斥锁 共享锁 乐观锁与悲观锁1 2.1. 自旋锁 ...
- linux执行sh脚本文件命令
linux执行sh脚本文件命令 很多时候需要多个命令来完成一项工作,而这个工作又常常是重复的,这个时候我们自然会想到将这些命令写成sh脚本,下次执行下这个脚本一切就都搞定了,下面就是发布代码的一个脚本 ...

