ASP.NET实现用户在线检测的类源码(转贴)

来源:互联网 发布:注销淘宝实名认证 编辑:程序博客网 时间:2024/05/02 15:06
//online.cs(用户在线检测)
/*程序实现思路:

该用户有以下几个属性:
name:用户名
sessionID:用户ID,通过它唯一表示一个用户
iswhere :附加信息,用户当前所在位置
lasttime:用户登陆时间
curtime:本次刷新时间

在客户端,使用一个IFRAME,装载一个刷新页面,每隔XX秒更新一下他的名字对应的curtime,就表示他仍然在

在服务器端,建立一个守护线程,每隔固定时间就运行一遍,然后判断当前所有用户列表中的时间间隔是否超出了规定的时间,如果超出,则将该用户从在线列表中删除,这样就可以做到检测用户是否在线了,而如果再单独
写个用户离线后的处理,就可以解决好多人问到的:用户意外吊线后的处理。
*/

#define DEBUG

using System;
using System.Data;
using System.Data.SqlClient;
using System.Collections ;
using System.Threading ;
using System.Web;
using System.Diagnostics;

namespace SohoProject
{
    //定义了一个结构
    public struct User
    {
     public string name;
     public DateTime lasttime; 
     public DateTime curtime;
     public string sessionid;
  public string ip;
     public string iswhere;
    }

 public class OnLineUser
 {
  private static DataTable _alluser;
 
  //只读属性
  public DataTable alluser{
   get{return _alluser;}
  }

  public OnLineUser()
  {
   if(_alluser==null)
   {
    //define user list
    // Declare variables for DataColumn and DataRow objects.
    _alluser = new DataTable("onlineuser");

    DataColumn myDataColumn;
 
    // Create new DataColumn, set DataType, ColumnName and add to DataTable.   
    myDataColumn = new DataColumn();
    myDataColumn.DataType = System.Type.GetType("System.String");
    myDataColumn.ColumnName = "name";
    myDataColumn.AutoIncrement = false;
    myDataColumn.Caption = "name";
    myDataColumn.ReadOnly = false;
    myDataColumn.Unique = false;
    _alluser.Columns.Add(myDataColumn);
 
 
    // Create sessionid column.
    myDataColumn = new DataColumn();
    myDataColumn.DataType = System.Type.GetType("System.String");
    myDataColumn.ColumnName = "sessionid";
    myDataColumn.AutoIncrement = false;
    myDataColumn.Caption = "sessionid";
    myDataColumn.ReadOnly = false;
    myDataColumn.Unique = true;
    _alluser.Columns.Add(myDataColumn);

    // Create ip column.
    myDataColumn = new DataColumn();
    myDataColumn.DataType = System.Type.GetType("System.String");
    myDataColumn.ColumnName = "ip";
    myDataColumn.AutoIncrement = false;
    myDataColumn.Caption = "ip";
    myDataColumn.ReadOnly = false;
    myDataColumn.Unique = false;
    _alluser.Columns.Add(myDataColumn);

    // Create iswhere column.
    myDataColumn = new DataColumn();
    myDataColumn.DataType = System.Type.GetType("System.String");
    myDataColumn.ColumnName = "iswhere";
    myDataColumn.AutoIncrement = false;
    myDataColumn.Caption = "iswhere";
    myDataColumn.ReadOnly = false;
    myDataColumn.Unique = false;
    _alluser.Columns.Add(myDataColumn);

    // Create iswhere column.
    myDataColumn = new DataColumn();
    myDataColumn.DataType = System.Type.GetType("System.DateTime");
    myDataColumn.ColumnName = "lasttime";
    myDataColumn.AutoIncrement = false;
    myDataColumn.Caption = "lasttime";
    myDataColumn.ReadOnly = false;
    myDataColumn.Unique = false;
    _alluser.Columns.Add(myDataColumn);

    // Create iswhere column.
    myDataColumn = new DataColumn();
    myDataColumn.DataType = System.Type.GetType("System.DateTime");
    myDataColumn.ColumnName = "curtime";
    myDataColumn.AutoIncrement = false;
    myDataColumn.Caption = "curtime";
    myDataColumn.ReadOnly = false;
    myDataColumn.Unique = false;
    _alluser.Columns.Add(myDataColumn);
   }
  }


  //功能说明:将当前用户加入在线列表
  //如果该用户的数据当前仍然在在线列表中,则暂时先不让该用户登陆,提示用户存在
  public bool  AddUserToOnLine(User user)
  {
#if DEBUG
   (new SohoProject.SohoDebug()).WriteToDoc("开始进入<将当前用户加入在线列表>....");
   (new SohoProject.SohoDebug()).WriteToDoc("/r/n");
#endif


   //开始搜索是否已经存在该用户,如果存在则是改变数据,否则添加新的用户
   string strExpr;
   strExpr = "sessionid='" + user.sessionid + "'";
   DataRow[] curUser;
   // Use the Select method to find all rows matching the filter.
#if DEBUG
   (new SohoProject.SohoDebug()).WriteToDoc("搜索字符串:" + strExpr);
   (new SohoProject.SohoDebug()).WriteToDoc("/r/n");
#endif


   curUser = _alluser.Select(strExpr);

#if DEBUG
   (new SohoProject.SohoDebug()).WriteToDoc(strExpr);
   (new SohoProject.SohoDebug()).WriteToDoc(curUser.Length.ToString());
#endif


   if (curUser.Length >0 )
   {
    for(int i = 0; i < curUser.Length; i ++)
    {
     curUser[i]["curtime"]=DateTime.Now;
     curUser[i]["iswhere"]=user.iswhere;
    }
   }
   else
   {
    //直接加入新的数据
    DataRow myRow;
    try
    {
     myRow = _alluser.NewRow();
     // Then add the new row to the collection.
     myRow["name"] = user.name;
     myRow["ip"] = user.ip;
     myRow["iswhere"] = user.iswhere;
     myRow["lasttime"] = user.lasttime;
     myRow["curtime"] = DateTime.Now;
     myRow["sessionid"] = user.sessionid;
     _alluser.Rows.Add(myRow);
    }
    catch(Exception e)
    {
     throw(new Exception(e + "--------------------" +  e.ToString())) ;
    }
   }
   _alluser.AcceptChanges();
   return true;
  } 
 


  //功能说明:判断某用户是否在线,本部分暂时不用
  //返回值:TRUE代表在线,FALSE不在
  public  Boolean IsUserOnLine(string name)
  {
   //需要先判断用户是否已经在用户列表中了
   //开始搜索是否已经存在该用户,如果存在则是改变数据,否则添加新的用户
   string strExpr;
   strExpr = "name ='" + name + "'";
   DataRow[] curUser;
   // Use the Select method to find all rows matching the filter.
   curUser = _alluser.Select(strExpr);

   if (curUser.Length >0 )
   {
    return true;   
   }
   else
   {
    return false;
   }
  }
       
  //功能说明:更新用户在线时间
  //返回值:最新的在线用户列表
  public Boolean CheckUserOnLine(string name,string iswhere,string sessionid,string ip)
  {
#if DEBUG
   (new SohoProject.SohoDebug()).WriteToDoc("开始进入检查用户方法....");
   (new SohoProject.SohoDebug()).WriteToDoc("");
#endif

   //需要先判断用户是否已经在用户列表中了
   User newuser=new User();
   newuser.name= name;
   newuser.iswhere= iswhere;
   newuser.lasttime=newuser.curtime=DateTime.Now;
   newuser.sessionid=sessionid;
   newuser.ip=ip;

   OnLineUser alluser= new OnLineUser();
   alluser.AddUserToOnLine(newuser);


#if DEBUG
   (new SohoProject.SohoDebug()).WriteToDoc("离开检查用户方法....");
#endif

   return true;
  }
 }
   
    //定义在线用户类
    public class OnLineUser_old
    {
     private static ArrayList _alluser ;  //定义用户
    
        public ArrayList alluser
        {
         get{return _alluser;}
         set{_alluser=value;}
        }
       
        public OnLineUser_old()  //构造函数
        {
         if(_alluser==null)
         {
          _alluser=new ArrayList();
         }
        }

        //功能说明:将当前用户加入在线列表
        //如果该用户的数据当前仍然在在线列表中,则暂时先不让该用户登陆,提示用户存在
        public bool  AddUserToOnLine(User user)
        {
         //需要先判断用户是否已经在用户列表中了
         if(_alluser==null)
         {
          _alluser.Add(user);
          return (true);
         }
         else
         {
    for ( int i = 0 ; i < _alluser.Count ; i ++)
          {
           //循环判断用户是否已经存在           SohoProject.User tempuser = (SohoProject.User)_alluser[i] ;

           if( tempuser.sessionid.Equals(user.sessionid))
           {
      //更新用户在线时间
      tempuser.name=user.name;
      tempuser.curtime=DateTime.Now;
      tempuser.iswhere=user.iswhere;
      tempuser.sessionid=user.sessionid;
      tempuser.ip=user.ip;
      alluser[i]=tempuser;
      return(true);
      //return(true); //用户已经存在,则直接退出           }
         }
          _alluser.Add(user);
          return (true);
         }
        } 
       
        //功能说明:判断某用户是否在线,本部分暂时不用
  //返回值:TRUE代表在线,FALSE不在
        public  Boolean IsUserOnLine(string name)
        {
         //需要先判断用户是否已经在用户列表中了
         if(_alluser==null)
         {
          return (false);
         }
         else
         {
          for ( int i = 0 ; i < _alluser.Count ; i ++)
          {
           //循环判断用户是否已经存在           SohoProject.User tempuser = (SohoProject.User)_alluser[i] ;
           if(tempuser.name.ToLower().Equals(name.ToLower()))
           {
            return(true) ;
           }
         }
          return (false);
         }
        }
       
        //功能说明:更新用户在线时间
  //返回值:最新的在线用户列表
        public Boolean CheckUserOnLine(string name,string iswhere,string sessionid,string ip)
        {
         //需要先判断用户是否已经在用户列表中了
         if(_alluser!=null)
         {
          User newuser=new User();
    newuser.name= name;
    newuser.iswhere= iswhere;
    newuser.lasttime=newuser.curtime=DateTime.Now;
    newuser.sessionid=sessionid;
    newuser.ip=ip;
   
    //OnLineUser alluser= new OnLineUser();
    AddUserToOnLine(newuser);
   }
   return(false);
        }
    }
   
   
   
    /*
    下面开始建立守护线程类:
    (注:此处,开始写的时候本来想做成单件模式的,不过由于以前没有做过这个东西,所以反而发生
    了很多问题,最后决定放弃而使用现有的格式)
    */
    public class CheckOnline
    {
     const int DELAY_TIMES = 10000 ;    //定义执行的时间间隔为5秒
     const int DELAY_SECONDS=60;     //将用户掉线时间设置为30秒
    
  private Thread thread ;      //定义内部线程
  private static bool _flag=false;   //定义唯一标志
 
  public CheckOnline()
  {
         if (!_flag)
         {
          _flag= true;
             this.thread = new Thread(new ThreadStart(ThreadProc)) ;
             thread.Name = "online user" ;
             thread.Start() ;
            }
        }
 
 
        internal void ThreadProc()
        {
            while(true) 
            {
//              SohoProject.OnLineUser temp=new SohoProject.OnLineUser();  //定义一个用户对象
//      for (int i=0 ;i< temp.alluser.Count;i++)
//          {
//           User tmpuser=(User)temp.alluser[i];
//           //我是将该用户的最新时间加上30秒,然后和当前时间比较,小与当前时间,
//           //则表示该用户已经吊线,则删除他的记录
//           if(tmpuser.curtime.AddSeconds(DELAY_SECONDS).CompareTo(DateTime.Now)<0)
//           {
//            temp.alluser.RemoveAt(i);
//           }
//          }

    SohoProject.OnLineUser temp=new SohoProject.OnLineUser();  //定义一个用户对象
    //开始检查是否有用户过期了    string strExpr;
    //tmpuser.curtime.AddSeconds(DELAY_SECONDS).CompareTo(DateTime.Now)<0
    strExpr = "curtime < '" + DateTime.Now.AddSeconds( 0 - DELAY_SECONDS) + "'";
#if DEBUG
    (new SohoProject.SohoDebug()).WriteToDoc(strExpr);
#endif

    DataRow[] curUser;
    // Use the Select method to find all rows matching the filter.
    curUser = temp.alluser.Select(strExpr);

    if (curUser.Length >0 )
    {
     //删除这些记录
     for(int i = 0; i < curUser.Length; i ++)
     {
      curUser[i].Delete();
     }
     temp.alluser.AcceptChanges();
    }
                Thread.Sleep(DELAY_TIMES) ;
            }
        }
    }
}

编译程序:

csc /t:library /out:../bin/online.dll /r:system.dll online.cs

有了DLL剩下的就是在页面中使用了

我没有针对那个系统特定的去做,读者可以自己将他加如任何一个系统

使用中只要新建立个用户:User newuser=new User();
然后将这个用户加入用户列表中就可以了

由于我没有什么固定用户,测试程序中就用的是sessionid做的用户名
程序如下

//global.aspx

<%@Import namespace="System"%>
<%@Import namespace="Soholife"%>
<%@Import Namespace="System.Collections"%>

<script language="C#" runat="server">
    void Session_Start(Object sender, EventArgs E)
    {
        //得到在线用户列表
        User newuser=new User();
        newuser.name=Session.SessionID ;
        newuser.sessionid=Session.SessionID ;
        newuser.lasttime=newuser.curtime=DateTime.Now;
        
        OnLineUser alluser= new OnLineUser();
        if(alluser.AddUserToOnLine(newuser))
        {
            Response.Write ("用户添加成功<br>");
        }
        else
        {
            Response.Write ("用户添加失败<br>");
        }
        
    }

    void Session_End(Object sender, EventArgs E) {
        
    }


    
    void Application_Error(Object sender, EventArgs E) {
    //  Context.ClearError();
    //  Response.Redirect("errorpage.htm");
    }

</script>

原创粉丝点击