欢迎访问 生活随笔!

凯发k8官方网

当前位置: 凯发k8官方网 > 编程语言 > asp.net >内容正文

asp.net

asp.net在线用户列表精确版——解决用户意外退出在线列表无法及时更新问题 -凯发k8官方网

发布时间:2024/10/8 asp.net 0 豆豆
凯发k8官方网 收集整理的这篇文章主要介绍了 asp.net在线用户列表精确版——解决用户意外退出在线列表无法及时更新问题 小编觉得挺不错的,现在分享给大家,帮大家做个参考.
最近所做的一个项目需要用到的在线用户列表,上网搜索了一下发现现有的凯发k8官方网的解决方案对用户意外退出的处理均不是太理想。一般来说,用户离开系统的方式有三种:主动注销、会话超时、直接关闭浏览器,对于前两种,我们很容易便可将该用户从在线列表中清除,关键是第三种(很多用户都是直接关闭窗口的~~郁闷ing),程序无法捕获窗口关闭的精确时间,只能等到会话超时后在能将该用户清除出在线列表,假设我们设置会话超时时间为60分钟,而用户登陆系统随便浏览一个页面就以关闭浏览器的方式退出的话,我们要在将近1小时后才能从在线列表中将该用户清除出去(想象一下,系统显示n多人在线,可能除了你之外其他的n-1人都关机走人了,汗一个先```),而本文将尝试寻找一个凯发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 = @"

  • 上一篇:
  • 下一篇:
网站地图