1

I am trying create a small web application that allows a user to "login" and "logout." What I am currently having a problem with is allowing the client to send constant "heartbeats" or messages to the server to notify that it is still active.

This is more of a logical question. What I want to do is have a while(1) loop in php that checks if n number of heartbeats have been skipped. I still want the client and server to be able to interact while this loop is going on (essentially I want the server to behave as if it has a separate "check_for_heartbeats" thread.

How does one accomplish this using php? I am running XAMPP at the moment. Any help would be much appreciated.

Edit: To clarify, what I want to do is be able to catch a browser close event even on instances where the window.unload event won't fire (e.g. a client gets disconnected from the internet). In this case, having a thread to monitor heartbeats seems to be the most intuitive solution, though I'm not sure how to make it happen in php.

Edit 2: isLoggedIn() is just helper function that checks to see if a session boolean variable ($_SESSION['is_logged_in')) is set.

Edit Final: Okay, so I now understand exactly what the comments and responses were saying. So to paraphrase, here is the potential solution: Have Javascript code to send "heartbeats" to the server. The server will add a timestamp associated with these beats. Modify the database to hold these time stamps Query the entire "timestamps" table (more likely a 'users' table with a 'timestamp' attribute), and see if the difference between NOW and last timestamp is greater than some threshold. "Log off" any users passed this threshold.

The only issue is if there is just one user logged in or if all users lose connection at the same time - but in these cases, no one else will be there to see that a user has lost connection.

This is a combination of multiple responses, but I think chris's response takes care of the majority of the issue. Thank you to both chris and Alex Lunix for the helpful contributions. :D

Here is a code snippet for a better explanation

Server Side:

function checkBeats()
{
    while(isLoggedIn())
    {
        // it's been > 30 secs since last heartbeat
        if((time() - $_SESSION['heartbeat']) > 30)
        {
            logout();
            break;
        }
    }
}
funseiki
  • 9,167
  • 9
  • 36
  • 59
  • Not sure. I figure yes, because I want to be able to catch issues like if the user's browser has crashed (in that case the window.onbeforeunload event isn't fired and I have nothing other than the heartbeats to make an ajax request). – funseiki Feb 12 '12 at 07:38
  • 1
    I'm still confused what you need this for. What is the goal, to make sure a user is still logged in? Why can't you just check every time they make a request, and log the last request time as a measure of activity? – Wesley Murch Feb 12 '12 at 07:52
  • Sorry about the confusion. Yes, I want to make sure the user is still logged in. The heartbeats on the client side (i.e. ajax requests from javascript code) allow me to make sure a user is still online, but where do I do the actual "checking" to make sure they are not offline? Right now, I have it so that anytime a window.unload event is fired the client sends an ajax message saying it the window has closed. Anytime the onload event is fired, the client tells the server that the window is open. Now, what about if the client's internet connection fails - how does the server find out? – funseiki Feb 12 '12 at 07:56
  • php doesn't do things without people visiting pages, so in order to check the heartbeat time and set them as logged off you'll either need another programming language checking, or you need to incorporate a system in which it checks all of the heartbeat times at each page load and hope that people visit enough to refresh the database. – John V. Feb 12 '12 at 15:25
  • I was just hoping for consistency in the database. If a user loses internet connection, there is really no way for the server to find out because no heartbeats will be sent. If I implement it in your suggested way (which is pretty much how I'm doing it now), the user will appear "logged in" for the entire time that his/her internet has been disconnected until the user decides to visit the page again. This is problematic primarily for other users that may be looking for people who are also "logged in" and may be talking to someone who appears logged in but has actually lost connection. – funseiki Feb 12 '12 at 18:17

2 Answers2

2

What i usually do is call a php file using javascript (jQuery) and update a database or whatevery you like. This question might answer yours: Whats the easiest way to determine if a user is online? (PHP/MYSQL)

Community
  • 1
  • 1
chris
  • 1,055
  • 11
  • 14
  • Thanks for the response, but I think what I am trying to do is the inverse of the suggested answer. What I was hoping for was some way to make sure the user's heartbeats have not stopped to handle cases where a user loses connection, the browser crashes, or any other instance where the window.unload event won't fire to ensure that the user isn't considered "logged on" in the database. – funseiki Feb 12 '12 at 07:40
  • So if i get this right, you wan't to get notified directly when a user closes the browser, or even unplug the internet cable? – chris Feb 12 '12 at 16:12
  • How are you planning to use this? How do you check if a person is signed in? (Your function "isLoggedIn"). I'm guessing facebook is doing it the way i suggested in the link (For their live chat) as if i've got two facebook accounts and i'm signed in on 2 different computers, i will still show as online for about 30secs after i shutdown the 2nd computer. To make it more "live" you will have to update the online status more often. – chris Feb 12 '12 at 16:22
  • Agreed, I am able to catch events where the user purposefully closes and opens a window through the window.onbeforeunload event and window.onload event, respectfully. I make ajax posts during those events to notify the server that a user has just left the webpage, but the real issue stems from the server handling heartbeats to make it more "live." How do I enable an infinite loop in server space (through php)- which will handle the heartbeat monitoring- that will not block other server requests? – funseiki Feb 12 '12 at 18:26
  • Well, making an infinite PHP loop isn't a good idea. And i don't know how you will grab all the users "heartbeats" from a single while loop, as session variables will only be accessible when a user is getting a page. What do you plan to do with the "online" status for the users? As i don't really understand why you need to "logout();" the user. If you set a session it would only be valid until they close their browser, which will automatically sign them out. If you have a database with users and a timestamp, you can run a cronjob every x second and do whatever you want with offline users! – chris Feb 12 '12 at 19:44
1

You could use ajax to heartbeat a script that changes the heartbeats session variable, and just at the top of every script do this check (put it in a function and call that of course):

// it's been > 30 secs since last heartbeat
if((time() - $_SESSION['heartbeat']) > 30)
{
    logout();
}

Edit: If you want the database to reflect that status instantly instead of when they next visit the page, you'll need to use MySQL. Without using another program (such as a java program) to check the database the only thing I can think of is to add this at the top of every page (in a function that gets called of course):

mysql_query("UPDATE `users` SET `loggedin`=0 WHERE heartbeat<".time()-30);

Which would update every user, which means the accuracy of the loggedin value would be set by the frequency of page views.

John V.
  • 4,652
  • 4
  • 26
  • 26
  • There would be no need to logout. If the user goes offline the script won't be called. – Umbrella Feb 12 '12 at 03:44
  • The point is if they don't get the heart beat the next time they visit they would need to log back in, but your right in that the system wouldn't recognize that they were offline until that next visit. – John V. Feb 12 '12 at 15:22
  • Sorry for the lack of understanding, I have posted an edit that may be what you were referring to. Thanks for the insight! – funseiki Feb 12 '12 at 18:53