4

I've created a very simple multiuser game for learning purposes.

As users log on, each other user gets an update of all currently logged in users.

When a user logs in, it simply sets a value for that user in the SQL database to 1. When they're logged out, the value should be 0.

I'm using $(window).unload(function() {}); to try to catch tab/browser closes, but it only sortof works.

Two questions:

  1. Is there a better way to catch browser or tab close?

  2. In the event that it misses the tab close, or their machine crashes, or internet connection dies, or the user simply walks away from the machine, I want to go ahead and log them out automatically.

I'm using an HTML/Jquery frontend with PHP backend. What can I do to accomplish the second question? I assume I need to do it in PHP.. we're working under the assumption that the browser is likely no longer even around, hence not processing jquery stuff. Can PHP do something on an continuous timer that checks to see if the user is still around... without simply having the users click a button every 10 seconds?

Edit: There's a potential solution here: How to detect if a user has logged out, in php? But I'm using ajax to avoid page refreshes. Ideally, the user will never f5 the page, or click any buttons (I'm testing, remember, this is not a for real app). Will PHP see last activity without a full page refresh?

Edit2: I've added the following code to my PHP, with a corresponding jquery function using setInterval

if (isset ($_POST['keepalive'])) {
    if (filter_input(INPUT_POST,'keepalive') == '1') {
        $name = $_SESSION['name'];
        $time = time();
        mysql_query("UPDATE tictac_names SET keep_alive = '$time' WHERE name ='$name'") or die(mysql_error());
    }   
}

This plugs a unix epoc timestamp into my table, which will be super easy for simple calculations.

My question now is: How do I tell PHP to run a check for each logged in user ever X number of seconds? My PHP backend file is primarily just set to catch post variables and run code, then hand it back to jquery. Since this code is intended to log out inactive browsers/users, I can't rely on jquery sending a request to PHP, and there's no refresh of the PHP. Do I need to do some kind of cron job or some bizarreness to get PHP to check for all users who have not updated in the last X seconds?

Help!

Community
  • 1
  • 1
jeremy
  • 663
  • 1
  • 8
  • 27

6 Answers6

0

A possible way to only catch a user who comes back to the site after they closed the window could be using a database for user ID, IP and time like so:

$_SESSION['ip'] = $_SERVER['HTTP_CLIENT_IP'];
if(isset($_SESSION['ip'])){
    if(Logedin){ // This login detection can be set by cookies can very depending on situation
        mysql_query("INSERT INTO users SET user_login=\"".'1'."\",user_id=\"".$idfromlogin."\",user_ip=\"".$_SESSION['ip']."\",user_time=\"".time();."\"");
    }

Then we can check this every time a page loads against the time(); if the user closes window by "X" button the session is over. Now we have to start a new session but that's why we saved the time in the database.

$_SESSION['ip'] = $_SERVER['HTTP_CLIENT_IP'];
if(isset($_SESSION['ip'])){
    if (!$sql = mysql_query("SELECT * FROM users WHERE user_ip=".$_SESSION['ip'])){
        die('Error: ' . mysql_error());
    }

    $row = mysql_fetch_array($sql);
    if ($row['user_time'] + 10 * 60 < time()){ // this is 10 minutes have passed
        // now to find the user database by the session database the logins is your method of loging in a user from logins database with pass and name
        if (!$user = mysql_query("UPDATE logins SET user_isloggedin=\"".'0'."\" WHERE user_id=".$row['user_id'])){ //from the users database
            die('Error: ' . mysql_error());
        }
    }

This only shows a way to check IP if they came back and the recorded time has passed previous. This does not show how to catch when some one presses "X" button. IP's can change so I would write a check IP function:

function getRealIpAddr(){
    if (!empty($_SERVER['HTTP_CLIENT_IP'])){   //check IP from share internet
        $ip=$_SERVER['HTTP_CLIENT_IP'];
    } elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])){   //to check IP is pass from proxy
        $ip=$_SERVER['HTTP_X_FORWARDED_FOR'];
    }else{
        $ip=$_SERVER['REMOTE_ADDR'];
    }
    return $ip;
}
Joe
  • 15,205
  • 8
  • 49
  • 56
DarkSide
  • 1
  • 1
0

I assume that, users are shown as online and offline on logout. Destroying session or cookie will require client browser in working mode.

Solution

I also assume there is a timestamp column maintained. Set an interval to check time-gap between current TS and Last Timestamp. Also update your own TS against your id to current TS.

setInterval(function(){ 
    $.ajax({
        url: "/backend.php?userid=id",
        success: function(resoponse){
            console.log(response);
        }
    });
}, 10000);

backend.php

$user_id = $_GET["userid"];
$query = "select * from table name where (GETDATE() - timestamp) > 60";
$resut = mysqli_query($con, $query);
while($row = mysqli_fetch_assoc($result)){
    //set there status = 0 as offline
    $other_user_id = $row['user_id'];
    mysqli_query($con, "update tablename set status = 0 where user_id = '$other_user_id'");
}
//update your own timestamp
mysqli_query($con, "update tablename set timestamp = GETDATE() where user_id='$user_id'");

This would check user activity, or basically check if that js is running or not. If browser was closed then TS for that user won't get updated hence GETDATE() - timestamp will be greater than 60. Now other users who would be running the web app would also run the same script, checking and updating all users status as per condition. When user closes his tab he would still be online for at least 1 minute.

I had a similar problem and found solution here PHP auto logout on tab close.

Kishor Parida
  • 295
  • 1
  • 10
0

Don't know about the first question, but how about a suggestion on the second:

When the user is 'active', will they be causing page requests fairly regularly? If so, you could have a system whereby a logged-on user is periodically logged in your SQL database, with a timestamp. Then have another script look up all those users whose timestamps are older than a specified period (whatever you like, eg 10 seconds) and have them set to '0'.

I could suggest some code but maybe this isn't what you're looking for - let me know.

EDIT: OK, the link from your edit seems to have been answered with a similar system to what I just suggested. If you use AJAX you can call a php script periodically in the background to set and check timestamps from the SQL table.

Michael Bromley
  • 4,792
  • 4
  • 35
  • 57
0

You could implement a $_SESSION based solution, like Gumbo answered this question. Then you could adapt it to handle your database requirements.

Community
  • 1
  • 1
quantme
  • 3,609
  • 4
  • 34
  • 49
0

if you used html5 socket connections as your way of connecting to the server, your socket server script would know when a subscriber disconnects. this would also allow you to push data to all the clients in real time without long polling. the only problem is I don't know what the support of html5 sockets is at the moment. I have done something similar using Flash, which also supports socket connections.

dqhendricks
  • 19,030
  • 11
  • 50
  • 83
0

Instead of just setting a flag when a user logs in, log a timestamp you can use to determine the time of log-in. Also, you can have your client, call-home using AJAX some PHP script to save in the database the timestamp of last user-activity.

You can then execute a session cleaner script periodically using a cron job in the server. The script would query the database to detect the stale sessions and do the log-off (set the logged on flag to 0). If the server has PHP CLI (Command Line Interface) installed, you can code the script in PHP.

Xint0
  • 5,221
  • 2
  • 27
  • 29