我为学习目的创建了一个非常简单的多用户游戏。
当用户登录时,每个其他用户都会获得所有当前登录用户的更新。
当用户登录时,它只是将SQL数据库中该用户的值设置为1.当他们注销时,该值应为0.
我正在使用$(window).unload(function(){});尝试捕捉标签/浏览器关闭,但它只能起作用。
两个问题:
有没有更好的方法来捕捉浏览器或标签关闭?
如果它没有关闭标签,或者他们的机器崩溃,或互联网连接中断,或者用户只是离开机器,我想继续自动登出。
我正在使用带有PHP后端的HTML / Jquery前端。我该怎么做才能完成第二个问题?我假设我需要在PHP中执行它...我们假设浏览器可能不再存在,因此不处理jquery的东西。 PHP可以在连续计时器上执行某些操作,该计时器会检查用户是否还在...而不是让用户每10秒钟点击一次按钮吗?
编辑: 这里有一个潜在的解决方案:How to detect if a user has logged out, in php? 但我正在使用ajax来避免页面刷新。理想情况下,用户永远不会 f5页面,或点击任何按钮(我正在测试,请记住,这不是真正的应用程序)。 PHP是否会在没有完整页面刷新的情况下查看上一个活动?
EDIT2: 我已经将以下代码添加到我的PHP中,并使用setInterval
添加了相应的jquery函数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());
}
}
这会将unix epoc时间戳插入到我的表中,这对于简单计算来说非常容易。
我现在的问题是:如何告诉PHP为每个登录用户运行一次X秒的检查?我的PHP后端文件主要用于捕获post变量和运行代码,然后将其交还给jquery。由于此代码旨在注销不活动的浏览器/用户,因此我不能依赖于jquery向PHP发送请求,并且不会刷新PHP。我是否需要做一些cron工作或一些奇怪的事情来让PHP检查所有在过去X秒内没有更新过的用户?
帮助!
答案 0 :(得分:0)
不知道第一个问题,但关于第二个问题的建议如何:
当用户“有效”时,他们是否会定期引起页面请求?如果是这样,您可以建立一个系统,通过该系统定期在SQL数据库中登录已登录的用户,并带有时间戳。然后让另一个脚本查找所有那些时间戳超过指定时间段的用户(无论你喜欢什么,例如10秒)并将它们设置为'0'。
我可以推荐一些代码,但也许这不是你想要的 - 请告诉我。
编辑:好的,您编辑的链接似乎已经使用了与我刚刚建议的类似的系统。如果您使用AJAX,您可以在后台定期调用php脚本来设置和检查SQL表中的时间戳。
答案 1 :(得分:0)
您可以实施基于$ _SESSION的解决方案,例如Gumbo answered this question。然后你可以调整它来处理你的数据库需求。
答案 2 :(得分:0)
如果您使用html5套接字连接作为连接服务器的方式,则套接字服务器脚本将知道订户何时断开连接。这也可以让您在没有长时间轮询的情况下实时将数据推送到所有客户端。唯一的问题是我不知道html5套接字的支持目前是什么。我使用Flash做了类似的事情,它也支持套接字连接。
答案 3 :(得分:0)
不是仅在用户登录时设置标志,而是记录可用于确定登录时间的时间戳。此外,您可以让您的客户端,使用AJAX调用回家一些PHP脚本,以在数据库中保存上次用户活动的时间戳。
然后,您可以使用服务器中的cron作业定期执行会话清理程序脚本。该脚本将查询数据库以检测陈旧的会话并执行注销(将登录标志设置为0)。如果服务器安装了PHP CLI(命令行界面),则可以使用PHP编写脚本代码。
答案 4 :(得分:0)
在关闭窗口后只捕获回到站点的用户的一种可能方法是使用数据库获取用户ID,IP和时间,如下所示:
$_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();."\"");
}
然后,如果用户在会话结束时按“X”按钮关闭窗口,则每次页面加载time();
时都可以检查此项。现在我们必须开始一个新的会话,但这就是我们在数据库中节省时间的原因。
$_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());
}
}
这只显示了一种检查IP的方法,如果它们回来并且记录的时间已经过去了。这并没有显示当某人按下“X”按钮时如何捕捉。 IP可以改变,所以我会写一个检查IP功能:
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;
}
答案 5 :(得分:0)
我假设用户在注销时显示为在线和离线。销毁会话或cookie将需要客户端浏览器处于工作模式。
<强>解决方案强>
我还假设维护了一个时间戳列。设置间隔以检查当前TS和上次时间戳之间的时间间隔。同时根据您的身份更新您自己的TS到当前的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'");
这将检查用户活动,或基本上检查js是否正在运行。如果浏览器已关闭,那么该用户的TS将无法更新,因此GETDATE() - 时间戳将大于60.现在,运行Web应用程序的其他用户也将运行相同的脚本,检查并更新所有用户根据条件的状态。 当用户关闭他的标签时,他仍然会在线至少1分钟。
我遇到了类似的问题,并在PHP auto logout on tab close找到了解决方案。