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 ...
随机推荐
- 【吉光片羽】ie6兼容性的几个点
1.浮动换行.自己写个导航,li向左浮动,到ie6下全部错开了. --> 还是在现有bootstrap框架的基础上修改样式保险一些. <div id="mymenu" ...
- java提高篇(六)-----使用序列化实现对象的拷贝
我们知道在Java中存在这个接口Cloneable,实现该接口的类都会具备被拷贝的能力,同时拷贝是在内存中进行,在性能方面比我们直接通过new生成对象来的快,特别是在大对象的生成上,使得性能的提升非常 ...
- 【IOS】Target membership
Target membership是指XCode中,一个文件属于哪一个工程,在XCode左侧的工程面板中选中一个文件,在XCode右侧的属性面板中会显示其Target Membership,如下图. ...
- Linux创建用户(转)
这篇文章总结的太好了,让我没动力新写一篇了,啊哈哈哈哈. 源自:http://www.cnblogs.com/ylan2009/articles/2321177.html Linux 系统是一个多用户 ...
- telnet小结
几百年前就开始听说telnet了,却直到最近才真正完全搞懂!... http://www.cnblogs.com/wusthjp/archive/2012/01/05/2312975.html 可能要 ...
- Android开发学习之路-自定义ListView(继承BaseAdapter)
大三学生一个,喜欢编程,喜欢谷歌,喜欢Android,所以选择的方向自然是Android应用开发,开博第一篇,希望以后会有更多的进步. 最近在做一个记账App的时候,需要一个Activity来显示每个 ...
- CAR
24.编写一个Car类,具有String类型的属性品牌,具有功能drive: 定义其子类Aodi和Benchi,具有属性:价格.型号:具有功能:变速: 定义主类E,在其main方法中分别创建Aodi和 ...
- 在 lua 中实现函数的重载
在 lua 中实现函数的重载.注:好吧,lua中原来可以实现重载...local function create() local arg_table = {} local function dispa ...
- Atitit 跨平台异常处理(2)--------异常转换 -----java c# js异常对象结构比较and转换
Atitit 跨平台异常处理(2)--------异常转换 -----java c# js异常对象结构比较and转换 { "@type":"java.lang.Runti ...
- Unity3D大风暴之入门篇(海量教学视频版)
智画互动开发团队 编 ISBN 978-7-121-22242-9 2014年2月出版 定价:79.00元 328页 16开 编辑推荐 长达800分钟的高清教学视频,手把手教会初学者 数个开发案例 ...