1、 新建一个名为ActiveUser的类,存储单个活动用户数据。
2 /// 单个在线用户数据,无法继承此类。
3 /// </summary>
4 public sealed class ActiveUser
5 {
6 private readonly string _ticket; //票据名称
7 private readonly string _username; //登陆用户名
8 private readonly string _truename; //登陆用户名
9 private readonly string _roleid; //角色
10 private readonly DateTime _refreshtime; //最新刷新时间
11 private readonly DateTime _activetime; //最新活动时间
12 private readonly string _clientip; //登陆IP
13
14 public ActiveUser(string Ticket,string UserName,string TrueName,string RoleID,string ClientIP) {
15 this._ticket=Ticket;
16 this._username=UserName;
17 this._truename=TrueName;
18 this._roleid=RoleID;
19 this._refreshtime=DateTime.Now;
20 this._activetime=DateTime.Now;
21 this._clientip=ClientIP;
22 }
23
24 public ActiveUser(string Ticket,string UserName,string TrueName,string RoleID,DateTime RefreshTime,DateTime ActiveTime,string ClientIP) {
25 this._ticket=Ticket;
26 this._username=UserName;
27 this._truename=TrueName;
28 this._roleid=RoleID;
29 this._refreshtime=RefreshTime;
30 this._activetime=ActiveTime;
31 this._clientip=ClientIP;
32 }
33
34 public string Ticket { get{return _ticket;} }
35 public string UserName { get{return _username;} }
36 public string TrueName { get{return _truename;} }
37 public string RoleID { get{return _roleid;} }
38 public DateTime RefreshTime { get{return _refreshtime;} }
39 public DateTime ActiveTime { get{return _activetime;} }
40 public string ClientIP { get{return _clientip;} }
41
42 }
43
44
2 /// PassPort 存储在线用户列表。
3 /// </summary>
4 public class PassPort
5 {
6 private static DataTable _activeusers;
7 private int _activeTimeout;
8 private int _refreshTimeout;
9
10 /// <summary>
11 /// 初始化在线用户表。
12 /// </summary>
13 private void userstableFormat()
14 {
15 if(_activeusers==null) {
16 _activeusers = new DataTable("ActiveUsers");
17 DataColumn myDataColumn;
18 System.Type mystringtype;
19 mystringtype = System.Type.GetType("System.String");
20 System.Type mytimetype;
21 mytimetype = System.Type.GetType("System.DateTime");
22 myDataColumn = new DataColumn("Ticket",mystringtype);
23 _activeusers.Columns.Add(myDataColumn);
24 myDataColumn = new DataColumn("UserName",mystringtype);
25 _activeusers.Columns.Add(myDataColumn);
26 myDataColumn = new DataColumn("TrueName",mystringtype);
27 _activeusers.Columns.Add(myDataColumn);
28 myDataColumn = new DataColumn("RoleID",mystringtype);
29 _activeusers.Columns.Add(myDataColumn);
30 myDataColumn = new DataColumn("RefreshTime",mytimetype);
31 _activeusers.Columns.Add(myDataColumn);
32 myDataColumn = new DataColumn("ActiveTime",mytimetype);
33 _activeusers.Columns.Add(myDataColumn);
34 myDataColumn = new DataColumn("ClientIP",mystringtype);
35 _activeusers.Columns.Add(myDataColumn);
36 }
37 }
38
39 public PassPort()
40 {
41 userstableFormat(); //初始化在线用户表
42 //活动超时时间初始化 单位:分钟
43 try { _activeTimeout=int.Parse(ConfigurationSettings.AppSettings["ActiveTimeout"]); }
44 catch{ _activeTimeout=60; }
45 //自动刷新超时时间初始化 单位:分钟
46 try { _refreshTimeout=int.Parse(ConfigurationSettings.AppSettings["RefreshTimeout"]); }
47 catch{ _refreshTimeout=1; }
48 }
49
50 //全部用户列表
51 public DataTable ActiveUsers
52 {
53 get{return _activeusers.Copy();}
54 }
55
56 /// <summary>
57 /// 新用户登陆。
58 /// </summary>
59 public void Login(ActiveUser user,bool SingleLogin)
60 {
61 DelTimeOut(); //清除超时用户
62 if(SingleLogin){
63 //若是单人登陆则注销原来登陆的用户
64 this.Logout(user.UserName,false);
65 }
66 DataRow myRow;
67 try
68 {
69 myRow = _activeusers.NewRow();
70 myRow["Ticket"] = user.Ticket.Trim();
71 myRow["UserName"] = user.UserName.Trim();
72 myRow["TrueName"] = ""+user.TrueName.Trim();
73 myRow["RoleID"] = ""+user.RoleID.Trim();
74 myRow["ActiveTime"] = DateTime.Now;
75 myRow["RefreshTime"] = DateTime.Now;
76 myRow["ClientIP"] = user.ClientIP.Trim();
77 _activeusers.Rows.Add(myRow);
78 }
79 catch(Exception e)
80 {
81 throw(new Exception(e.Message));
82 }
83 _activeusers.AcceptChanges();
84
85 }
86
87 /// <summary>
88 ///用户注销,根据Ticket或UserName。
89 /// </summary>
90 private void Logout(string strUserKey,bool byTicket)
91 {
92 DelTimeOut(); //清除超时用户
93 strUserKey=strUserKey.Trim();
94 string strExpr;
95 strExpr =byTicket ? "Ticket='" + strUserKey +"'" : "UserName='" + strUserKey + "'";
96 DataRow[] curUser;
97 curUser = _activeusers.Select(strExpr);
98 if (curUser.Length >0 )
99 {
100 for(int i = 0; i < curUser.Length; i ++)
101 {
102 curUser[i].Delete();
103 }
104 }
105 _activeusers.AcceptChanges();
106 }
107
108 /// <summary>
109 ///用户注销,根据Ticket。
110 /// </summary>
111 /// <param name="strTicket">要注销的用户Ticket</param>
112 public void Logout(string strTicket){
113 this.Logout(strTicket,true);
114 }
115
116 /// <summary>
117 ///清除超时用户。
118 /// </summary>
119 private bool DelTimeOut()
120 {
121 string strExpr;
122 strExpr = "ActiveTime < '" + DateTime.Now.AddMinutes( 0 - _activeTimeout) + "'or RefreshTime < '"+DateTime.Now.AddMinutes( 0 - _refreshTimeout)+"'";
123 DataRow[] curUser;
124 curUser = _activeusers.Select(strExpr);
125 if (curUser.Length >0 )
126 {
127 for(int i = 0; i < curUser.Length; i ++)
128 {
129 curUser[i].Delete();
130 }
131 }
132 _activeusers.AcceptChanges();
133 return true;
134 }
135
136 /// <summary>
137 ///更新用户活动时间。
138 /// </summary>
139 public void ActiveTime(string strTicket)
140 {
141 DelTimeOut();
142 string strExpr;
143 strExpr = "Ticket='" + strTicket + "'";
144 DataRow[] curUser;
145 curUser = _activeusers.Select(strExpr);
146 if (curUser.Length >0 )
147 {
148 for(int i = 0; i < curUser.Length; i ++)
149 {
150 curUser[i]["ActiveTime"]=DateTime.Now;
151 curUser[i]["RefreshTime"]=DateTime.Now;
152 }
153 }
154 _activeusers.AcceptChanges();
155 }
156
157 /// <summary>
158 ///更新系统自动刷新时间。
159 /// </summary>
160 public void RefreshTime(string strTicket)
161 {
162 DelTimeOut();
163 string strExpr;
164 strExpr = "Ticket='" + strTicket + "'";
165 DataRow[] curUser;
166 curUser = _activeusers.Select(strExpr);
167 if (curUser.Length >0 )
168 {
169 for(int i = 0; i < curUser.Length; i ++)
170 {
171 curUser[i]["RefreshTime"]=DateTime.Now;
172 }
173 }
174 _activeusers.AcceptChanges();
175 }
176
177 private ActiveUser SingleUser(string strUserKey,bool byTicket)
178 {
179 strUserKey=strUserKey.Trim();
180 string strExpr;
181 ActiveUser myuser;
182 strExpr =byTicket ? "Ticket='" + strUserKey +"'" : "UserName='" + strUserKey + "'";
183 DataRow[] curUser;
184 curUser = _activeusers.Select(strExpr);
185 if (curUser.Length >0 )
186{
187 string myTicket=(string)curUser[0]["Ticket"];
188 string myUser=(string)curUser[0]["UserName"];
189 string myName=(string)curUser[0]["TrueName"];
190 string myRoleID=(string)curUser[0]["RoleID"];
191 DateTime myActiveTime=(DateTime)curUser[0]["ActiveTime"];
192 DateTime myRefreshtime=(DateTime)curUser[0]["RefreshTime"];
193 string myClientIP =(string)curUser[0]["ClientIP"];
194 myuser=new ActiveUser(myTicket,myUser,myName,myRoleID,myActiveTime,myRefreshtime,myClientIP);
195 }
196 else
197 {
198 myuser=new ActiveUser("","","","","");
199 }
200 return myuser;
201 }
202
203 /// <summary>
204 ///按Ticket获取活动用户。
205 /// </summary>
206 public ActiveUser SingleUser_byTicket(string strTicket)
207 {
208 return this.SingleUser(strTicket,true);
209 }
210
211 /// <summary>
212 ///按UserName获取活动用户。
213 /// </summary>
214 public ActiveUser SingleUser_byUserName(string strUserName)
215 {
216 return this.SingleUser(strUserName,false);
217 }
218
219 /// <summary>
220 ///按Ticket判断用户是否在线。
221 /// </summary>
222 public bool IsOnline_byTicket(string strTicket)
223 {
224 return (bool)(this.SingleUser(strTicket,true).UserName!="");
225 }
226
227 /// <summary>
228 ///按UserName判断用户是否在线。
229 /// </summary>
230 public bool IsOnline_byUserName(string strUserName)
231 {
232 return (bool)(this.SingleUser(strUserName,false).UserName!="");
233 }
234}
235
236
2 /// Refresh 执行更新自动刷新时间操作。
3 /// </summary>
4 public class Refresh: PlaceHolder
5 {
6 /// <summary>
7 /// 设置存储Ticket的Session名称,默认为Ticket。
8 /// </summary>
9 public virtual string SessionName
10 {
11 get{
12 object obj1 = this.ViewState["SessionName"];
13 if (obj1 != null){ return ((string) obj1).Trim(); }
14 return "Ticket";
15 }
16 set{
17 this.ViewState["SessionName"] = value;
18 }
19 }
20
21 protected override void Render(HtmlTextWriter writer)
22 {
23 string myTicket=(string)this.Page.Session[this.SessionName];
24 if(myTicket!=null)
25 {
26 PassPort myPass = new PassPort();
27 myPass.RefreshTime(myTicket);
28 writer.Write("OK:"+DateTime.Now.ToString());
29 }
30 else{
31 writer.Write("Sorry:"+DateTime.Now.ToString());
32 }
33 base.Render(writer);
34 }
35}
36
37
2 /// Script 生成执行xmlhttp的js脚本。
3 /// </summary>
4 public class Script: PlaceHolder
5 {
6 /// <summary>
7 /// 设置js自动刷新的间隔时间,默认为25秒。
8 /// </summary>
9 public virtual int RefreshTime
10 {
11 get
12 {
13 object obj1 = this.ViewState["RefreshTime"];
14 if (obj1 != null){return int.Parse(((string) obj1).Trim());}
15 return 25;
16 }
17 set
18 {
19 this.ViewState["RefreshTime"] = value;
20 }
21 }
22
23 protected override void Render(HtmlTextWriter writer)
24 {
25 //从web.config中读取xmlhttp的访问地址
26 string refreshUrl=(string)ConfigurationSettings.AppSettings["refreshUrl"];
27 string scriptString = @" <script language=""JavaScript"">"+writer.NewLine;
28 scriptString += @" window.attachEvent(""onload"", "+this.ClientID+@"_postRefresh);"+writer.NewLine;
29 scriptString += @" var "+this.ClientID+@"_xmlhttp=null;"+writer.NewLine;
30 scriptString += @" function "+this.ClientID+@"_postRefresh(){"+writer.NewLine;
31 scriptString += @" var "+this.ClientID+@"_xmlhttp = new ActiveXObject(""Msxml2.XMLHTTP"");"+writer.NewLine;
32 scriptString += @" "+this.ClientID+@"_xmlhttp.Open(""POST"", """+refreshUrl+@""", false);"+writer.NewLine;
33 scriptString += @" "+this.ClientID+@"_xmlhttp.Send();"+writer.NewLine;
34 scriptString += @" var refreshStr= "+this.ClientID+@"_xmlhttp.responseText;"+writer.NewLine;
35
36 scriptString += @" try {"+writer.NewLine;
37 scriptString += @" var refreshStr2=refreshStr;"+writer.NewLine;
38 //scriptString += @" alert(refreshStr2);"+writer.NewLine;
39 scriptString += @" }"+writer.NewLine;
40 scriptString += @" catch(e) {}"+writer.NewLine;
41 scriptString += @" setTimeout("""+this.ClientID+@"_postRefresh()"","+this.RefreshTime.ToString()+@"000);"+writer.NewLine;
42 scriptString += @" }"+writer.NewLine;
43 scriptString += @"<";
44 scriptString += @"/";
45 scriptString += @"script>"+writer.NewLine;
46
47 writer.Write(writer.NewLine);
48 writer.Write(scriptString);
49 writer.Write(writer.NewLine);
50 base.Render(writer);
51 }
52 }
53
54
===============================================
下面我简单介绍一下调用方法:
1、 新建一个名为OnlineUserDemo的asp.net web应用程序
2、 在vs的工具箱选项卡上右击,选择[添加/移除项],浏览定位到OnlineUser.dll,确定即可把Refresh 和Script添加到工具箱。
3、 把自动生成的WebForm1.aspx删除,并设置web.config
2 <add key="ActiveTimeout" value="30" />
3 <add key="RefreshTimeout" value="1" />
4 <add key="refreshUrl" value="refresh.aspx" />
5 </appSettings
2 if(myTicket!=null)
3 {
4 OnlineUser.PassPort myPassPort= new OnlineUser.PassPort();
5 if(myPassPort.IsOnline_byTicket(this.Session["Ticket"].ToString()))
6 {
7 myPassPort.ActiveTime(this.Session["Ticket"].ToString());
8 DataGrid1.DataSource=myPassPort.ActiveUsers;
9 DataGrid1.DataBind();
10 }
11 else{
12 //若在线用户列表中找不到当前用户,则定向到注销页面
13 Response.Redirect("Logout.aspx");
14 }
15 }
16 else{
17 Response.Redirect("Login.aspx");
18 }
19
2 {
3 //不能为空
4 String scriptString = @"<script language=JavaScript>";
5 scriptString += @"alert(""输入一个用户名\n"");";
6 scriptString += @"history.go(-1);";
7 scriptString += @"<";
8 scriptString += @"/";
9 scriptString += @"script>";
10 if(!this.Page.IsStartupScriptRegistered("Startup"))
11 this.Page.RegisterStartupScript("Startup", scriptString);
12 }
13 else{
14 OnlineUser.PassPort myPassPort= new OnlineUser.PassPort();
15 string myTicket=DateTime.Now.ToString("yyyyMMddHHmmss");
16 string myUser=TextBox1.Text.Trim();
17 string myClintIP=this.Request.UserHostAddress;
18 this.Session["Ticket"]=myTicket;
19 OnlineUser.ActiveUser myActiveUser=new OnlineUser.ActiveUser(myTicket,myUser,myUser,"test",myClintIP);
20 myPassPort.Login(myActiveUser,true);
21 Response.Redirect("Online.aspx");
22 }
23
2 myPassPort.Logout(this.Session["Ticket"].ToString());
3 this.Session["Ticket"]="";
4
2<%@ Page %>
3<cc2:Refresh id="myRefresh" runat="server"></cc2:Refresh>
4把Refresh.txt改名为Refresh.aspx
5
8、 编译生成工程。
===============================================
下面进行功能测试:
1、 打开浏览器,在地址栏输入
http://你机器的IP地址/onlineuserdemo/Login.aspx
2、 输入一个用户名(假设是test1)登陆,自动转到online.aspx页面
3、 找同网段的另外一台机器(设你的机器为a,这台机器为b),重复执行第一步。
4、 输入一个用户名(假设是test2)登陆,自动转到online.aspx页面
5、 在b机器不断刷新online.aspx,若发现test1用户RefreshTime每过25秒自动更新一次而ActiveTime不变(这个时候a机器不要刷新页面啊),则证明a机器的自动刷新生效。
6、 在a机器不断刷新online.aspx,若发现test2用户RefreshTime每过25秒自动更新一次而ActiveTime不变(这个时候b机器不要刷新页面啊),则证明b机器的自动刷新生效。
7、 直接关闭一台机器(假设是a)上的online.aspx浏览窗口,在另一台机器(就是b啦)上刷新online.aspx,若发现1分钟后test1掉线在线用户只剩下test2,证明通过_refreshTimeout清除在线用户成功。
8、 若5、6、7三步正常,则大功告成,否则就再调试调试~~