简体   繁体   English

确定用户是否在线的最简单方法是什么? (PHP/MYSQL)

[英]Whats the easiest way to determine if a user is online? (PHP/MYSQL)

Is there a way I can piggy back sessions to know if the user is online?有没有办法可以通过会话来了解用户是否在线?

Ie: use logs on, I set a $_SESSION variable, user times out- cookie Garbage collector updates the database to update their status as offline.即:使用登录,我设置了一个 $_SESSION 变量,用户超时 cookie 垃圾收集器更新数据库以更新其状态为离线。

EDIT: I want a solution that does not involve times or dates. EDIT:我想要一个不涉及时间或日期的解决方案。 I want something to ride on sessions or something similar.我想要一些骑在会议或类似的东西。 Guessing if someone is online is not good enough for what I need.猜测是否有人在线不足以满足我的需求。

Don't bother with figuring out the differences between timezones.不要费心弄清楚时区之间的差异。 That's not necessary.那没有必要。

Whenever the user accesses a page, update a field in their record of the Users table last-updated-time.每当用户访问页面时,更新用户表上次更新时间记录中的字段。 Then do a query for all users having a last-updated-time within the last 5 minutes.然后查询在过去 5 分钟内具有最后更新时间的所有用户。 Anything more than this, and they are considered "offline."除此之外的任何东西,它们都被视为“离线”。

If you use your server-time, via the NOW() function in MySQL, you'll side-step calculating differences between timezones.如果您使用服务器时间,通过 MySQL 中的 NOW() 函数,您将回避计算时区之间的差异。

This is the standard way of tracking how many users are presently online (Meaning, active within the last couple of minutes).这是跟踪当前在线用户数量的标准方法(意思是,在过去几分钟内处于活动状态)。

Constantly Updated不断更新

If you would like to know they are still active even when they're not jumping from page to page, include a bit of javascript to ping your server every 60 seconds or so to let you know they are still alive.如果您想知道即使它们没有在页面之间跳转,它们仍然处于活动状态,请包含一些 javascript 以每 60 秒左右 ping 您的服务器,让您知道它们仍然存在。 It'll work the same way as my original suggestion, but it will update your records without requiring them to be frantically browsing your site at least once every five minutes.它的工作方式与我最初的建议相同,但它会更新您的记录,而无需他们至少每五分钟疯狂浏览一次您的网站。

var stillAlive = setInterval(function () {
    /* XHR back to server
       Example uses jQuery */
    $.get("stillAlive.php");
}, 60000);

What you are asking for (after the clarification) is, by definition, impossible.根据定义,您所要求的(在澄清之后)是不可能的。 HTTP is a connectionless protocol, so as soon as a user has hit a page and all the content comes back from the server to the user's browser, there is no connection between the two. HTTP 是一种无连接协议,因此一旦用户点击页面并且所有内容从服务器返回到用户的浏览器,两者之间就没有连接。 Someone is "online" with your website for less than a second.有人在您的网站上“在线”不到一秒钟。

One thing you could do is to have JavaScript on your web page make AJAX requests back to your server on a regular basis which includes identifying information, and a different AJAX request when the user leaves the page, using window.onbeforeunload .可以做的一件事是在您的网页上使用 JavaScript 将 AJAX 请求定期发送回您的服务器,其中包括识别信息,以及当用户离开页面时使用window.onbeforeunload发出不同的 AJAX 请求。

My way may not be the best way but since my site and userbase is all in mysql DB, when a user logins into my site,我的方式可能不是最好的方式,但由于我的网站和用户群都在 mysql DB 中,当用户登录我的网站时,

  1. I update the user table to say they are online我更新用户表说他们在线
  2. Insert them into an Online table将它们插入到在线表中
  3. Then I set a session with the current time然后我设置了一个当前时间的会话

Then on every page load I check for the online time session, if it exist, I check to see how old it is, if it is less then 5 minutes old, I do nothing, if it is older then 5 minutes, then I update the session time again with current time and also update the online users table with the time然后在每个页面加载我检查在线时间会话,如果它存在,我检查它的年龄,如果它小于 5 分钟,我什么都不做,如果它大于 5 分钟,然后我更新使用当前时间再次使用会话时间,并使用时间更新在线用户表

Then I have a cron job that runs every 10 - 15 minutes that deletes any uses from online table and marks there user table as offline if there online time has updated within X amount of minutes然后我有一个 cron 作业,它每 10 - 15 分钟运行一次,它从在线表中删除任何使用,如果在线时间在 X 分钟内更新,则将用户表标记为离线

It sounds like your "is the person online" comparison logic isn't taking into account the timezones.听起来您的“是在线人”比较逻辑没有考虑时区。 If you are dealing with timezones in this manner, I strongly recommend that you store all your times in GMT, and convert them to local time for your users right before you display them.如果您以这种方式处理时区,我强烈建议您将所有时间存储在 GMT 中,并在显示之前将它们转换为用户的当地时间。 This will make any comparison operations very simple.这将使任何比较操作变得非常简单。

There's a nice SO thread about timezones here .有一个关于时区一个不错的SO线程在这里

One thing I would advise is to store this kind of information in memory with for example memcached or mysql heap or redis.我建议的一件事是将此类信息存储在内存中,例如使用 memcached 或 mysql 堆或 redis。 Because otherwise the database will be hit a lot.因为否则数据库会被打很多。

Store the time-zone in the table, and use it in a calculation to find that users local time in comparison to the local time of the user viewing the page.将时区存储在表中,并在计算中使用它来查找用户本地时间与查看页面的用户的本地时间。

Edit:编辑:

Better yet, store all times as the server time, and base all calculations relative only to the server time.更好的是,将所有时间存储为服务器时间,并仅根据服务器时间进行所有计算。

Depends on your situation, it may be better for you to create a separate table "whose-online" with the columns: "ip" and "last-updated-time" and query/update this table every time a user loads a page.根据您的情况,您最好创建一个单独的表“whose-online”,其中包含“ip”和“last-updated-time”列,并在每次用户加载页面时查询/更新此表。

On page load queries may include :页面加载查询可能包括

  1. Update/insert "whose-online" table for current user based on ip.根据 ip 更新/插入当前用户的“whose-online”表。
  2. Delete "expired" rows (can also be done periodically using cronjob).删除“过期”行(也可以使用 cronjob 定期完成)。
  3. Count "active" users.计算“活跃”用户。

Benefits of using this technique :使用这种技术的好处

  1. If a user is not logged in, he/she is still being counted/tracked.如果用户没有登录,他/她仍然被计数/跟踪。
  2. Depends on the amount of users you have, querying this table may be quicker.根据您拥有的用户数量,查询此表可能会更快。

Note: If you use this you should want to take into consideration that any pageview will create a row in your table so based on useragent you can disregard bots or only count the popular ones (Firefox, IE, Safari, Opera, etc).注意:如果您使用它,您应该考虑到任何网页浏览都会在您的表格中创建一行,因此基于用户代理,您可以忽略机器人或仅计算流行的机器人(Firefox、IE、Safari、Opera 等)。

The solution that I have implemented for this is to, on every page load by an authenticated user, set/reset a memcache var such as "user_{userid} isonline" => true and expire it in 5 minutes.我为此实施的解决方案是,在经过身份验证的用户加载的每个页面上,设置/重置内存缓存变量,例如“user_{userid} isonline”=> true 并在 5 分钟后过期。 Then check if the var is in the cache when I access the user's info.然后在我访问用户信息时检查 var 是否在缓存中。 Depending on the size of your user base, if you want to get a list of everyone online, you could use a memcache getmulti call with an array of "user {userid}_isonline" keys for all of your users.根据您的用户群的大小,如果您想获得每个人的在线列表,您可以对所有用户使用带有“user {userid}_isonline”键数组的 memcache getmulti 调用

of course, this really depends on how often a user will change pages on your site... to get a more accurate representation of the users online, you could implement an ajax xmlhttprequest call on your page running at a small interval (30 seconds or so) that resets the memcache var, and have the memcache var expire in less time (1 minute to account for possible browser issues).当然,这实际上取决于用户更改您网站上页面的频率……要获得更准确的在线用户表示,您可以在您的页面上以很小的时间间隔(30 秒或所以)重置内存缓存变量,并使内存缓存变量在更短的时间内过期(1 分钟以解决可能的浏览器问题)。 This is not COMPLETELY accurate, but as http does not have a persistent connection to the server, you are pretty limited on what you can do.这并不完全准确,但由于 http 没有与服务器的持久连接,因此您可以执行的操作非常有限。

IF you require an up to the second representation of who is online, you could maybe have a flash app loaded in your page that connects to a jabber server, then just check if that particular user is logged in on the server.如果您需要最多第二个表示谁在线,您可能会在您的页面中加载一个连接到 jabber 服务器的 flash 应用程序,然后只需检查该特定用户是否已登录服务器。

Here's a way on how to get the difference between two dates from a database in minutes, then check for the difference and set the online/offline status.这是一种如何在几分钟内从数据库中获取两个日期之间差异的方法,然后检查差异并设置在线/离线状态。

$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);
    }
} 

You can also use the onunload tag... On the body More information here ( https://www.w3schools.com/jsref/event_onunload.asp )您还可以使用onunload标签...在正文中更多信息在这里( https://www.w3schools.com/jsref/event_onunload.asp

This way you don't have to wait 4 -5 minutes for the user to get offline.这样您就不必等待 4 -5 分钟让用户下线。

But you should still use the ajax update method in-case the user's browser crashes...但是您仍然应该使用 ajax 更新方法,以防用户的浏览器崩溃...

Edit: As @Quentin pointed out in the comments you may not be able to send out requests but there is a way you can do it... Explained in more detail in this Article .编辑: @Quentin在评论中指出的,你可能无法发出请求,但有一种方法可以做到这一点...在详细解释这条
So basically they are using the sendBeacon() Here is an Example所以基本上他们正在使用sendBeacon()这是一个例子

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

NOTE: Although it should be kept in mind that this should not be the only method you should depend upon, and should implement for redundancy...注意:虽然应该记住,这不应该是您应该依赖的唯一方法,并且应该实现冗余......

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM