43

有没有办法可以通过会话来了解用户是否在线?

即:使用登录,我设置了一个 $_SESSION 变量,用户超时-cookie 垃圾收集器更新数据库以将其状态更新为离线。

EDIT:我想要一个不涉及时间或日期的解决方案。我想要一些东西来参加会议或类似的事情。猜测某人是否在线不足以满足我的需要。

4

10 回答 10

112

不要费心弄清楚时区之间的差异。那没有必要。

每当用户访问页面时,更新其用户表上次更新时间记录中的字段。然后查询所有在过去 5 分钟内具有最后更新时间的用户。除此之外,它们被视为“离线”。

如果您使用服务器时间,通过 MySQL 中的 NOW() 函数,您将避开计算时区之间的差异。

这是跟踪当前在线用户数量的标准方法(意思是,在最后几分钟内活跃)。

不断更新

如果您想知道即使它们没有从一个页面跳转到另一个页面,它们仍然处于活动状态,请包含一些 javascript 以每 60 秒左右对您的服务器执行一次 ping 操作,以让您知道它们还活着。它的工作方式与我最初的建议相同,但它会更新您的记录,而无需他们至少每五分钟疯狂浏览一次您的网站。

var stillAlive = setInterval(function () {
    /* XHR back to server
       Example uses jQuery */
    $.get("stillAlive.php");
}, 60000);
于 2009-06-27T01:34:14.143 回答
5

我的方式可能不是最好的方式,但由于我的网站和用户群都在 mysql DB 中,当用户登录我的网站时,

  1. 我更新用户表说他们在线
  2. 将它们插入到在线表中
  3. 然后我用当前时间设置会话

然后在每次页面加载时,我检查在线时间会话,如果存在,我检查它的年龄,如果它小于 5 分钟,我什么也不做,如果它超过 5 分钟,那么我更新使用当前时间再次使用会话时间,并使用时间更新在线用户表

然后我有一个每 10 - 15 分钟运行一次的 cron 作业,它从在线表中删除任何使用,如果在线时间在 X 分钟内更新,则将用户表标记为离线

于 2009-07-30T08:44:26.793 回答
5

根据定义,您所要求的(在澄清之后)是不可能的。HTTP 是一种无连接协议,因此一旦用户点击了一个页面,并且所有内容都从服务器返回到用户的浏览器,两者之间就没有任何连接。有人在您的网站上“在线”不到一秒钟。

您可以做的一件事是让您的网页上的 JavaScript 使用window.onbeforeunload定期向您的服务器发出 AJAX 请求,其中包括识别信息和用户离开页面时的不同 AJAX 请求。

于 2009-06-28T02:52:49.487 回答
3

听起来您的“是在线人”比较逻辑没有考虑时区。如果您以这种方式处理时区,我强烈建议您将所有时间存储在 GMT 中,并在显示它们之前将它们转换为您的用户的本地时间。这将使任何比较操作变得非常简单。

这里有一个关于时区的不错的 SO 线程。

于 2009-06-27T01:34:03.223 回答
2

我建议的一件事是将这种信息存储在内存中,例如 memcached 或 mysql heap 或 redis。因为否则数据库会受到很大的打击。

于 2009-06-28T22:40:54.660 回答
0

我为此实现的解决方案是,在经过身份验证的用户加载的每个页面上,设置/重置 memcache var,例如“user_{userid} isonline”=> true 并在 5 分钟内使其过期。然后在我访问用户信息时检查 var 是否在缓存中。根据您的用户群的大小,如果您想获取在线所有人的列表,您可以使用 memcache getmulti 调用和所有用户的“user {userid}_isonline”键数组。

当然,这实际上取决于用户更改您网站上的页面的频率...为了更准确地表示在线用户,您可以在页面上以小间隔(30 秒或所以)这会重置 memcache var,并让 memcache var 在更短的时间内过期(1 分钟以解决可能的浏览器问题)。这并不完全准确,但是由于 http 没有与服务器的持久连接,因此您可以做的事情非常有限。

如果您需要最多第二个表示谁在线,您可能会在您的页面中加载一个连接到 jabber 服务器的 flash 应用程序,然后只需检查该特定用户是否已在服务器上登录。

于 2009-06-30T18:32:01.517 回答
0

将时区存储在表中,并在计算中使用它来查找用户本地时间与查看页面的用户本地时间的比较。

编辑:

更好的是,将所有时间存储为服务器时间,并将所有计算都基于服务器时间。

于 2009-06-27T01:31:53.150 回答
0

根据您的情况,您最好创建一个单独的表“whose-online”,其中包含以下列:“ip”和“last-updated-time”,并在每次用户加载页面时查询/更新此表。

页面加载查询可能包括

  1. 根据 ip 为当前用户更新/插入“谁在线”表。
  2. 删除“过期”行(也可以使用 cronjob 定期完成)。
  3. 计算“活跃”用户。

使用这种技术的好处

  1. 如果用户未登录,他/她仍在被计数/跟踪。
  2. 取决于您拥有的用户数量,查询此表可能会更快。

注意:如果你使用它,你应该考虑到任何页面浏览都会在你的表中创建一行,因此基于用户代理你可以忽略机器人或只计算流行的机器人(Firefox、IE、Safari、Opera 等)。

于 2009-06-28T01:14:24.567 回答
0

这是一种如何在几分钟内从数据库中获取两个日期之间差异的方法,然后检查差异并设置在线/离线状态。

$query = 'SELECT * FROM Users';
$result = mysqli_query($mysqli, $query);

foreach($result as $user){
    // date from the database
    $dbLastActivity = date("d-m-Y h:i:s a", strtotime($user['lastOnline']));
    // date now
    $now = date("d-m-Y h:i:s a", $date);

    // calculate the difference
    $difference = strtotime($now) - strtotime($dbLastActivity);
    $difference_in_minutes = $difference / 60;

    // check if difference is greater than five minutes
    if($difference_in_minutes < 5){
        // set online status
        $updateStatus = 'UPDATE Users SET Status="online" WHERE lastOnline="'.$user['lastOnline'].'"';
    } else {
        // set offline status
        $updateStatus = 'UPDATE Users SET Status="offline" WHERE lastOnline="'.$user['lastOnline'].'"';
    }

    // check if mysqli query was successful
    if (!$mysqli->query($updateStatus)){
        printf("Error Message %s\n", $mysqli->error);
    }
} 
于 2017-12-06T12:39:10.877 回答
-1

您还可以使用onunload标签... 关于正文 更多信息在这里(https://www.w3schools.com/jsref/event_onunload.asp

这样您就不必等待 4 -5 分钟让用户下线。

但是你仍然应该使用 ajax 更新方法以防用户的浏览器崩溃......

编辑: 正如@Quentin在评论中指出的那样,您可能无法发送请求,但有一种方法可以做到……在本文中进行了更详细的解释。
所以基本上他们使用的是sendBeacon() 这是一个例子

window.addEventListener("unload", function logData() {
  navigator.sendBeacon("/log", analyticsData);
});

注意:尽管应该记住,这不应该是您应该依赖的唯一方法,并且应该实现冗余......

于 2017-04-01T17:49:23.807 回答