具有自动刷新功能的实时访客计数器
我(和我们)的目标是构建一个无需用户干预即可自动刷新的组件(访问者计数器,放置在一个或多个网页中)。
可以使用您喜欢的服务器端技术,例如ASP.NET或PHP,但是,对于本文,我将使用Javascript+ASP.NET:我们在服务器端只需要一个ASPX页面,在客户端只需要一些功能。请记住,该概念可以用您想要的任何语言来实现。

就本文的目的而言,您应该(不是很深入地)了解:JavaScript,AJAX,ASP.NET,以及ASP.NET应用程序,回调函数和UUID的含义。
这个想法如下:我们需要在服务器端维护一个<unique_id,date>对的哈希字典,以便了解每个用户的上次操作时间;当current_time-last_action_time之间的差>30秒时,我们将认为用户已“过期”。显然,我们需要一种从客户端执行“time_stamp”刷新的方法,以避免删除活动用户。
在服务器端,我们只需要:
一种Dictionary<string,date>
一个ASPX页面
服务器端的伪代码如下:
OnApplicationStart:
ActiveUser = {}
OnPing(UUID): if not UUID in ActiveUser
add (UUID,Current_time) in ActiveUser else
update UUID in ActiveUser with Current_Time12345678复制代码类型:[javascript]
在客户端,我们需要执行一个简单的操作:用户首次进入我们的一个页面时,我们必须为其分配一个唯一的ID。该ID将存储在cookie中。对于以下每个访问,我们只需要读取cookie并将其发送到服务器即可。此外,我们需要一个显示活动用户数量的地方,以及一个用于查询服务器以便检索该数量的功能。因此,在客户端,我们需要:
一个<span>标签:)
一个<javascript>街区
一种允许我们生成唯一ID的方法(我将在本文中提供一个惰性方法)
客户端的伪代码如下:
PageLoad:
UUID = getCookie("MySite_UUID") if is null UUID
UUID = generate_uuid()
setCookie("MySite_UUID",UUID)
Ping_Server(UUID)
Every_5_seconds:
call_server_for_num()
Server_Callback(server_data) document.getElementyById("span1").value= server_data.nuser12345678910111213复制代码类型:[javascript]
使用代码
现在我们可以开始编码:我们创建一个名为serverside.aspx的新页面,其内容如下:
<%@ Page Language="vb" AutoEventWireup="false"
CodeBehind="serverside.aspx.vb" Inherits="RealTimeCouter.serverside" %>
<% ' we make sure that counter 'memory' is available
SyncLock Application
Dim ActiveUser As Dictionary(Of String, Date)
ActiveUser = CType(Application("ActiveUser"), Dictionary(Of String, Date))
If IsNothing(ActiveUser) Then
ActiveUser = New Dictionary(Of String, Date)
Application.Add("ActiveUser", ActiveUser)
End If
Application.Add("ActiveUser", ActiveUser)
End SyncLock
' on PING receive we check if UUID is known ' then save last action date and time
If Request("TYPE") = "PING" Then
Dim UUID As String = Request("UUID")
SyncLock CType(Application("ActiveUser"), Dictionary(Of String, Date))
If Not CType(Application("ActiveUser"), Dictionary(Of String, Date)).ContainsKey(UUID) Then
CType(Application("ActiveUser"), Dictionary(Of String, Date)).Add(UUID, Date.Now)
Else
CType(Application("ActiveUser"), Dictionary(Of String, Date))(UUID) = Date.Now
End If
End SyncLock
'on QUERY receive we return the number of UUID with
'last action timestamp value <30 sec from current timestamp
ElseIf Request("TYPE") = "QUERY" Then
Dim nusr As Integer = 0
For Each it As KeyValuePair(Of String, Date) In _
CType(Application("ActiveUser"), Dictionary(Of String, Date))
If Math.Abs(DateDiff(DateInterval.Second, it.Value, Date.Now)) <= 30 Then
nusr += 1
End If
Next it
Response.Write(nusr)
Return
End If
%>1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950复制代码类型:[javascript]
再次,创建一个名为clientside.aspx的新ASPX页面,其内容如下:
<%@ Page Language="vb" AutoEventWireup="false"
CodeBehind="clientside.aspx.vb" Inherits="RealTimeCouter.clientside" %><html xmlns="http://www.w3.org/1999/xhtml"><head runat="server">
<title></title>
<script type="text/javascript"
language="javascript" src="./utils.js"></script></head><body>
<div>
<span id="nvis">0 </span> visitors </div> <script language="javascript" defer="defer">
// Check for UUID of this user
var uuid = getCookie("site_uuid");
if (uuid == "") { var d = new Date(); var rnd = Math.floor((Math.random() * 100000) + 1);
uuid = rnd + '_' + d.getSeconds() + '_' + d.getMilliseconds() + '_' + d.getMinutes() + '_' + d.getHours();
setCookie("site_uuid", uuid);
} // send uuid to server (the ping)
var ping = getXMLReq();
ping.open("GET", "./serverside.aspx?TYPE=PING&UUID=" + uuid, true);
ping.send(); // Refresh number of visitors each 5 seconds
setInterval('loadXMLDoc()', 5000); // Refresh number of visitor at page load
loadXMLDoc(); function loadXMLDoc() { var xmlhttp = getXMLReq();
xmlhttp.onreadystatechange = function () {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
document.getElementById("nvis").innerText = xmlhttp.responseText;
}
}
xmlhttp.open("GET", "./serverside.aspx?TYPE=QUERY", true);
xmlhttp.send();
xmlhttp = none;
}</script></body></html>1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253复制代码类型:[javascript]
兴趣点
我们应该注意一些事情:
为了测试代码,您可以使用VS2010在Debug模式下运行项目并启动clientside.aspx:计数器将显示1。随后,您可以使用Chrome浏览器打开更多的“隐身”窗口,从而可以看到访问者数量在增加。如果停止打开新窗口,则可以查看正在减少的访问者数量,因为仅在打开新页面时才启动ping。(您可以更改此行为。)
ASP.NET回收可以清除ActiveUser变量(但这不是问题,因为在下次单击时,将再次对用户进行计数)
utils.js文件包含getCookie,setCookie和getXMLReq函数(为了使代码更简洁)。
服务器端代码可以用PHP实现,并且可以在与客户端不同的网站中运行。
本文随附的项目是使用VS2010Express编写的,但是可以在与.NET2.0兼容的任何IDE中执行。
UUID生成器非常非常懒。在高负载环境中可能会发生一些碰撞。
注意:在不同域之间使用此代码之前,将启用Ajax跨域调用。
