如何追踪我网站上用户的在线状态?
跟踪网站用户的在线状态是一个常见的需求,特别是在实时聊天或在线协作的场景中。为了实现这个功能,我们需要解决两个问题:原因和解决方法。
首先,为什么需要跟踪用户的在线状态?这是因为在实时聊天系统中,我们希望知道哪些用户当前在线,这样可以显示他们的在线状态并及时发送消息。另外,在某些情况下,我们可能需要知道用户何时离开聊天页面,以便在他们离开时做一些处理。
解决这个问题的方法是使用ajax技术。对于基于ajax的聊天系统,客户端会定期向聊天服务器发送请求,以检查是否有新的消息。如果有新的消息,我们可以在cookie或PHP会话中更新用户的在线状态。然后,我们可以将在线超时时间设置为稍长于更新频率。
例如,如果聊天系统通常每5秒向服务器请求新的消息,那么我们可以假设在10-15秒没有发送请求的用户已经不再在聊天页面上了。
如果我们使用的是非ajax的聊天系统(例如Java),我们仍然可以通过添加定期向服务器发送ajax请求来实现相同的功能,以确定用户是否在线。
在实现过程中,不建议将在线状态信息存储在数据库中。每隔几秒钟查询数据库以查看谁在线谁不在线会消耗大量资源,特别是对于大型网站来说。相反,我们应该将这些信息缓存起来,并在缓存上操作(速度非常快),而不是在数据库上操作(相比之下非常慢)。
在一般情况下,无法知道用户何时离开您的网页。但是您可以在幕后做一些事情,使得用户在网页上时频繁地从您的服务器加载一些内容,例如通过加载一个每分钟刷新的内容的<iframe>
:
<meta http-equiv="refresh" content="60">
这将导致一些额外的服务器负载,但它会实现您的要求(如果不是非常精确到秒)。
我从未使用过Iframe。那么我会在Iframe中每分钟更新一次mysql。我会将Iframe隐藏在首页中吗?
用户看不到Iframe页面刷新吗?
您可以使其显示一些有用的内容,例如“在线用户数”。然后,它会正确地可见地更新自身。
这不是一个好主意...最好使用JavaScript代码来实现。
如何跟踪我网站上的用户的在线状态?
为了解决这个问题,我们可以通过以下步骤完成:
首先,在index.php页面上实现该功能,可以通过异步方式(AJAX)将更新发送到服务器,告知服务器$_SESSION["userid"]仍然在线。
代码如下:
setInterval("update()", 10000); // 每10秒更新一次 function update() { $.post("update.php"); // 向update.php发送请求 }
update.php文件的代码如下:
session_start(); if ($_SESSION["userid"]) updateUserStatus($_SESSION["userid"]);
上述代码假设用户登录网站时将userid存储为会话变量。updateUserStatus()函数是一个简单的查询,如下所示:
UPDATE users SET lastActiveTime = NOW() WHERE userid = $userid
这样就解决了存储的问题。接下来,我们需要获取“在线”用户的列表。为此,我们还需要另一个jQuery调用和一个setInterval()调用:
代码如下:
setInterval("getList()", 10000) // 每10秒获取一次在线用户列表 function getList() { $.post("getList.php", function(list) { $("listBox").html(list); }); }
这个函数每10秒向服务器请求一些HTML内容。getList.php页面的代码如下:
session_start(); if (!$_SESSION["userid"]) die; // 不向未登录用户提供列表 $users = getOnlineUsers(); // 获取最近1分钟内的所有在线用户 $output = "
- ";
foreach ($users as $user) {
$output .= "
- ".$user["userName"]." "; } $output .= "
这样就会输出以下HTML代码:
- Jonathan Sampson
- Paolo Bergantino
- John Skeet
这个列表将被包含在名为"list"的jQuery变量中。回到上面的jQuery代码块,你会看到它在那里。
jQuery将取出这个列表,并将其放置在一个类名为"listBox"的div中:
希望这能帮助您解决问题。
+1,因为你以我的名字作为例子,并且没写错;)唯一的意见是setInterval("update()", 10000);最好写成setInterval(update, 10000);getList也是一样。
(显然,你必须事先声明函数的名字)
谢谢评论,Paolo。为什么要调用"update()"而不是"update"有什么好处?
没有什么直接的好处,只是使用定时器/间隔的引号功能被认为是不良实践。最好的做法是要么创建一个匿名函数,如setTimeout(function() { ... }),要么直接传递要调用的函数名。这并不是什么大问题,但一些“大牛”(Resig、Crockford)不喜欢这样做,我也同意他们的观点。
更多信息,请参考以下问题:stackoverflow.com/questions/797115/…和这个链接:developer.mozilla.org/en/DOM/window.setTimeout,其中写着“在替代语法中,代码是一个字符串,表示延迟毫秒后要执行的代码。(不推荐使用)”。