asp.net在线用户列表精确版——解决用户意外退出在线列表无法及时更新问题 -ag凯发k8国际
我的大概思路是,给每在线用户增加一个refreshtime属性,建立一个负责将当前用户的refreshtime属性设置为当前时间的单独页面(refresh.aspx),然后在系统的主要页面(也可以是所有页面)中通过xmlhttp不断地请求refresh.aspx页面,一旦用户关闭了与本系统相关的所有窗口,即以直接关闭浏览器的方式退出系统,那么该用户的refreshtime属性便不会自动更新了,我们再设置一个自动刷新的超时时间(这个要比会话超时短很多_refreshtimeout),当发现某用户超过_refreshtimeout的时间没有自动刷新,就能判定该用户已经以直接关闭浏览器的方式退出了。
假设我们设置会话超时时间为60分钟,自动刷新超时时间为1分钟,在客户端通过xmlhttp每隔25秒(之所以不设1分钟,是防止网速慢的时候访问refresh.aspx超时,个人感觉,不一定正确)访问一次refresh.aspx页面,在用户登陆、用户注销、检测用户是否在线的时候都执行清理超时用户(包括会话超时和自动刷新超时)操作,这样一来,在线用户列表的统计误差就由60分钟降至1分钟了。
==========================================
具体实现如下:
1、 新建一个名为activeuser的类,存储单个活动用户数据。
///
/// 单个在线用户数据,无法继承此类。
///
public sealed class activeuser
{
private readonly string _ticket; //票据名称
private readonly string _username; //登陆用户名
private readonly string _truename; //登陆用户名
private readonly string _roleid; //角色
private readonly datetime _refreshtime; //最新刷新时间
private readonly datetime _activetime; //最新活动时间
private readonly string _clientip; //登陆ip
public activeuser(string ticket,string username,string truename,string roleid,string clientip) {
this._ticket=ticket;
this._username=username;
this._truename=truename;
this._roleid=roleid;
this._refreshtime=datetime.now;
this._activetime=datetime.now;
this._clientip=clientip;
}
public activeuser(string ticket,string username,string truename,string roleid,datetime refreshtime,datetime activetime,string clientip) {
this._ticket=ticket;
this._username=username;
this._truename=truename;
this._roleid=roleid;
this._refreshtime=refreshtime;
this._activetime=activetime;
this._clientip=clientip;
}
public string ticket { get{return _ticket;} }
public string username { get{return _username;} }
public string truename { get{return _truename;} }
public string roleid { get{return _roleid;} }
public datetime refreshtime { get{return _refreshtime;} }
public datetime activetime { get{return _activetime;} }
public string clientip { get{return _clientip;} }
}
2、 新建一个名为passport的类,存储在线用户列表。
///
/// passport 存储在线用户列表。
///
public class passport
{
private static datatable _activeusers;
private int _activetimeout;
private int _refreshtimeout;
///
/// 初始化在线用户表。
///
private void userstableformat()
{
if(_activeusers==null) {
_activeusers = new datatable("activeusers");
datacolumn mydatacolumn;
system.type mystringtype;
mystringtype = system.type.gettype("system.string");
system.type mytimetype;
mytimetype = system.type.gettype("system.datetime");
mydatacolumn = new datacolumn("ticket",mystringtype);
_activeusers.columns.add(mydatacolumn);
mydatacolumn = new datacolumn("username",mystringtype);
_activeusers.columns.add(mydatacolumn);
mydatacolumn = new datacolumn("truename",mystringtype);
_activeusers.columns.add(mydatacolumn);
mydatacolumn = new datacolumn("roleid",mystringtype);
_activeusers.columns.add(mydatacolumn);
mydatacolumn = new datacolumn("refreshtime",mytimetype);
_activeusers.columns.add(mydatacolumn);
mydatacolumn = new datacolumn("activetime",mytimetype);
_activeusers.columns.add(mydatacolumn);
mydatacolumn = new datacolumn("clientip",mystringtype);
_activeusers.columns.add(mydatacolumn);
}
}
public passport()
{
userstableformat(); //初始化在线用户表
//活动超时时间初始化 单位:分钟
try { _activetimeout=int.parse(configurationsettings.appsettings["activetimeout"]); }
catch{ _activetimeout=60; }
//自动刷新超时时间初始化 单位:分钟
try { _refreshtimeout=int.parse(configurationsettings.appsettings["refreshtimeout"]); }
catch{ _refreshtimeout=1; }
}
//全部用户列表
public datatable activeusers
{
get{return _activeusers.copy();}
}
///
/// 新用户登陆。
///
public void login(activeuser user,bool singlelogin)
{
deltimeout(); //清除超时用户
if(singlelogin){
//若是单人登陆则注销原来登陆的用户
this.logout(user.username,false);
}
datarow myrow;
try
{
myrow = _activeusers.newrow();
myrow["ticket"] = user.ticket.trim();
myrow["username"] = user.username.trim();
myrow["truename"] = "" user.truename.trim();
myrow["roleid"] = "" user.roleid.trim();
myrow["activetime"] = datetime.now;
myrow["refreshtime"] = datetime.now;
myrow["clientip"] = user.clientip.trim();
_activeusers.rows.add(myrow);
}
catch(exception e)
{
throw(new exception(e.message));
}
_activeusers.acceptchanges();
}
///
///用户注销,根据ticket或username。
///
private void logout(string struserkey,bool byticket)
{
deltimeout(); //清除超时用户
struserkey=struserkey.trim();
string strexpr;
strexpr =byticket ? "ticket=" struserkey "" : "username=" struserkey "";
datarow[] curuser;
curuser = _activeusers.select(strexpr);
if (curuser.length >0 )
{
for(int i = 0; i < curuser.length; i )
{
curuser[i].delete();
}
}
_activeusers.acceptchanges();
}
///
///用户注销,根据ticket。
///
/// 要注销的用户ticket
public void logout(string strticket){
this.logout(strticket,true);
}
///
///清除超时用户。
///
private bool deltimeout()
{
string strexpr;
strexpr = "activetime < " datetime.now.addminutes( 0 - _activetimeout) "or refreshtime < " datetime.now.addminutes( 0 - _refreshtimeout) "";
datarow[] curuser;
curuser = _activeusers.select(strexpr);
if (curuser.length >0 )
{
for(int i = 0; i < curuser.length; i )
{
curuser[i].delete();
}
}
_activeusers.acceptchanges();
return true;
}
///
///更新用户活动时间。
///
public void activetime(string strticket)
{
deltimeout();
string strexpr;
strexpr = "ticket=" strticket "";
datarow[] curuser;
curuser = _activeusers.select(strexpr);
if (curuser.length >0 )
{
for(int i = 0; i < curuser.length; i )
{
curuser[i]["activetime"]=datetime.now;
curuser[i]["refreshtime"]=datetime.now;
}
}
_activeusers.acceptchanges();
}
///
///更新系统自动刷新时间。
///
public void refreshtime(string strticket)
{
deltimeout();
string strexpr;
strexpr = "ticket=" strticket "";
datarow[] curuser;
curuser = _activeusers.select(strexpr);
if (curuser.length >0 )
{
for(int i = 0; i < curuser.length; i )
{
curuser[i]["refreshtime"]=datetime.now;
}
}
_activeusers.acceptchanges();
}
private activeuser singleuser(string struserkey,bool byticket)
{
struserkey=struserkey.trim();
string strexpr;
activeuser myuser;
strexpr =byticket ? "ticket=" struserkey "" : "username=" struserkey "";
datarow[] curuser;
curuser = _activeusers.select(strexpr);
if (curuser.length >0 )
{
string myticket=(string)curuser[0]["ticket"];
string myuser=(string)curuser[0]["username"];
string myname=(string)curuser[0]["truename"];
string myroleid=(string)curuser[0]["roleid"];
datetime myactivetime=(datetime)curuser[0]["activetime"];
datetime myrefreshtime=(datetime)curuser[0]["refreshtime"];
string myclientip =(string)curuser[0]["clientip"];
myuser=new activeuser(myticket,myuser,myname,myroleid,myactivetime,myrefreshtime,myclientip);
}
else
{
myuser=new activeuser("","","","","");
}
return myuser;
}
///
///按ticket获取活动用户。
///
public activeuser singleuser_byticket(string strticket)
{
return this.singleuser(strticket,true);
}
///
///按username获取活动用户。
///
public activeuser singleuser_byusername(string strusername)
{
return this.singleuser(strusername,false);
}
///
///按ticket判断用户是否在线。
///
public bool isonline_byticket(string strticket)
{
return (bool)(this.singleuser(strticket,true).username!="");
}
///
///按username判断用户是否在线。
///
public bool isonline_byusername(string strusername)
{
return (bool)(this.singleuser(strusername,false).username!="");
}
}
3、 新建一个继承自placeholder名为refresh的类,执行更新自动刷新时间操作。
///
/// refresh 执行更新自动刷新时间操作。
///
public class refresh: placeholder
{
///
/// 设置存储ticket的session名称,默认为ticket。
///
public virtual string sessionname
{
get{
object obj1 = this.viewstate["sessionname"];
if (obj1 != null){ return ((string) obj1).trim(); }
return "ticket";
}
set{
this.viewstate["sessionname"] = value;
}
}
protected override void render(htmltextwriter writer)
{
string myticket=(string)this.page.session[this.sessionname];
if(myticket!=null)
{
passport mypass = new passport();
mypass.refreshtime(myticket);
writer.write("ok:" datetime.now.tostring());
}
else{
writer.write("sorry:" datetime.now.tostring());
}
base.render(writer);
}
}
4、 新建一个继承自placeholder名为script的类,生成执行xmlhttp的js脚本。。
///
/// script 生成执行xmlhttp的js脚本。
///
public class script: placeholder
{
///
/// 设置js自动刷新的间隔时间,默认为25秒。
///
public virtual int refreshtime
{
get
{
object obj1 = this.viewstate["refreshtime"];
if (obj1 != null){return int.parse(((string) obj1).trim());}
return 25;
}
set
{
this.viewstate["refreshtime"] = value;
}
}
protected override void render(htmltextwriter writer)
{
//从web.config中读取xmlhttp的访问地址
string refreshurl=(string)configurationsettings.appsettings["refreshurl"];
string scriptstring = @"
- 上一篇:
- 下一篇: