用PHP跟踪登录用户

时间:2011-08-24 12:22:13

标签: php session

我正在尝试用PHP和AJAX编写一个简单的网络聊天应用程序。

我需要知道所有打开的会话,以便我可以显示可以与之交谈的在线用户列表。我还需要注意注销,因为我使用“发送方和接收方都处于脱机状态”作为考虑终止聊天会话和删除消息的条件。

我正在跟踪数据库中登录的用户:在登录时添加一个条目并在注销时将其删除工作正常,但它并不全面,因为用户可以通过其他两种方式注销:

  • 服务器端会话在不活动后到期。
  • 客户端cookie在浏览器关闭时被破坏。使用某种onclose触发的AJAX似乎是一个坏主意(如果浏览器崩溃或其他什么?)。

最简单的解决方案似乎是保留最后一次活动的时间戳。我看到了一些问题:

  • AFAIK服务器端到期是基于机会的,所以它不准确(如果我得到3分钟的到期时间错误,这是3分钟,有些人可能正在与离线用户交谈,想知道为什么没有人回答)
  • 我必须经常查询数据库,以检查每个登录用户的上次活动时间与当前时间的比较。我没有看到我有效/何时这样做。每次需要在线用户列表时,这样做似乎很愚蠢。

任何帮助表示赞赏。我自己编码,因为我不知道任何可以与现有用户数据库集成的网络聊天框架,如果我错了,请纠正我。

7 个答案:

答案 0 :(得分:1)

我认为您无法通过关闭浏览器,互联网连接问题等来缓解持续查询以确定用户是否已注销,但您可能会让每个客户端都做出来每5秒向服务器发出一次AJAX请求以更新上次活动时间,并让服务器上的应用程序认为用户“已注销”,如果他们已经错过了3-4次连续请求(即他们的上一次活动时间> 20次)秒)。

在客户端,您可以在每次客户端向另一个用户发送消息时检查上次活动时间,并在发生这种情况时回复他们已注销。如果他们尝试与其他用户聊天,您也可以立即拨打电话查看他们的状态。然后,您可以每隔30秒检查用户列表中所有用户的状态。这样,如果他正在聊天的人意外地离线,你的客户会得到非常快速的反馈。

答案 1 :(得分:1)

您可以反转您的模式,用推送通知系统替换您的Ajax拉动行为。

通过这种方式,您可以实时通知聊天用户登录和注销新聊天成员。我从来没有在实践中做过这样的事情,但我已经读过这种技术,对于像你这样的案件看起来非常有趣。

它比ajax拉动方式稍微困难一点,但是一旦实现了主要结构,您就可以轻松添加功能,性能会更好。

我发现的一些链接很有用:

这是一个涉及javascript聊天的railscast剧集,实现在rails中,但即使你不理解rails,你也应该能够遵循它来获取核心概念:http://railscasts.com/episodes/260-messaging-with-faye

答案 2 :(得分:0)

我不确定你是否需要概率除数,但这是我自动注销人员所做的事情:

ini_set('session.gc_maxlifetime',3600); // 1 hour
ini_set('session.gc_probability',1); // it does garbage cleaning EVERY time
ini_set('session.gc_divisor',1); // it does garbage cleaning EVERY time
session_start();

答案 3 :(得分:0)

您当前使用的大部分数据和您需要的数据都存储在PHP会话中 - 如何从信息中获取用户ID并不明显。

如果切换到使用数据库绑定的会话处理程序,那么一切都变得非常简单。我有一个快速的谷歌 - 并有很多例子。但很多人(例如this one)在回读会话时没有检查到期日。 OTOH我链接的示例确实显示将用户ID添加到sesion记录 - 稍后您将需要它。所以会话读取处理函数应该是这样的:

 read:
 SELECT session_data, username
 FROM sessions
 WHERE session_id=' . session_id() . '
 AND last_updated>= ' . date('YmdHis', time()-ini_get('session.gc_maxlifetime'))

并获取所有当前登录的用户:

 SELECT username
 FROM sessions
 WHERE last_updated>= ' . date('YmdHis', time()-ini_get('session.gc_maxlifetime'))

...让(重写的)会话垃圾收集器自动清除冗余数据。

HTH

答案 4 :(得分:0)

首先分开您的顾虑。 就“在线用户列表”而言,您可以使用数据库&看来你已经想通了。 (即使某些人没有正确登出,显示一些额外的在线用户也不会造成太大的伤害)

现在,对于聊天应用,要检查用户是否仍在线,您必须使用ajax。 没有其他办法。当然,总会有一个黑客,我不知道。 当你在这里回答时看到图像image(stackoverflow)。它会不断检查时间是否过去了(并且你输入了新的东西)&保存副本。

答案 5 :(得分:0)

您似乎最关心的是性能,并且您已经了解了(主要)实现细节。只需将处理会话的表的类型更改为“内存”,这将降低为每个请求查询数据库的性能成本几乎为零,因为您直接从RAM获取数据。只需确保每次用户明确注销时删除会话,或者将用户标记为非活动状态。

但无论你做什么实现需要客户端和服务器之间持续通信的东西都无法通过HTTP完美地完成。但是如果你提出合理的超时等,它将在99%的时间内起作用。

答案 6 :(得分:0)

我迟到了这个派对,但是让我给我两分钱。

在这种特定情况下,不需要针对错误通知的推送系统。也没有必要使用cron。让我解释一下:

说A,B和C在聊天室& B的浏览器崩溃了,所以他的会话到期了。现在,服务器认为B仍在那里,但她不是。你如何更新A& C?当A& C ASK进行更新。检查B的最后一个keepalive时间戳,并确定他们的会话已经过期。

如果所有A,B& C崩溃,然后这种情况从未发生过,我听到你问。谁在乎?现在没有人看到我们的错误!唯一的缺点是保持他们的聊天室活着,这需要花费一些数据库空间。这可以在创建另一个聊天会话时清理。

最后的要点:

  1. 保留最后一次采取行动的时间戳。
  2. 使用用户事件循环遍历时间戳并取出枯木。
  3. 如果是用户,则会将其记录下来。在聊天室的情况下,这将是那些已经过期的。