[英]Keeping track of logged in users in PHP
我正在尝试用PHP和AJAX编写一个简单的网络聊天应用程序。
我需要知道所有打开的会话,以便我可以显示可以与之交谈的在线用户列表。 我还需要注意注销,因为我使用“发送方和接收方都处于脱机状态”作为考虑终止聊天会话和删除消息的条件。
我正在跟踪数据库中登录的用户:在登录时添加一个条目并在注销时将其删除工作正常,但它并不全面,因为用户可以通过另外两种方式注销:
最简单的解决方案似乎是保留最后一个活动的时间戳。 我看到了一些问题:
任何帮助赞赏。 我自己编码,因为我不知道任何可以与我现有的用户数据库集成的网络聊天框架,如果我错了,请纠正我。
我认为你不会做太多工作来缓解不断查询以确定用户是否通过关闭浏览器,互联网连接问题等来注销,但你可能让每个客户端发出一个AJAX请求每隔5秒钟到服务器更新一次活动时间,并让服务器上的应用程序认为用户“已注销”,如果他们已经错过了3-4次连续请求(即他们的上一次活动时间> 20秒)。
在客户端,您可以在每次客户端向另一个用户发送消息时检查上次活动时间,并在发生这种情况时回复他们已注销。 如果他们尝试与其他用户聊天,您也可以立即拨打电话查看他们的状态。 然后,您可以每隔30秒检查用户列表中所有用户的状态。 这样,如果他正在聊天的人意外地离线,那么您的客户会得到相当快速的反馈。
您可以反转您的模式,用推送通知系统替换您的Ajax拉动行为。
通过这种方式,您可以实时通知聊天用户登录和注销新聊天成员。 我在实践中从来没有做过这样的事情,但我已经读过这种技术,对于像你这样的案例来说这似乎很有趣。
它比ajax拉动方式稍微强一点,但是一旦实现了主要结构,您可以轻松添加功能,性能会更好。
我发现的一些链接很有用:
这是一个涉及javascript聊天的railscast剧集,实现在rails中,但即使你不理解rails,你也应该能够按照它来获取核心概念: http : //railscasts.com/episodes/ 260的消息传递与-菲
我不确定你是否需要概率和除数,但这是我自动注销人员的方法:
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();
您当前使用的大多数数据和您需要的数据都存储在PHP会话中 - 如何从信息中派生用户ID并不明显。
如果切换到使用数据库绑定的会话处理程序,那么一切都变得非常简单。 我有一个快速的谷歌 - 并有很多例子。 但很多人(例如这一个 )在回读会话时没有检查到期日。 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
首先分开你的顾虑。 就“在线用户列表”而言,您可以使用数据库,而您似乎已经想到了这一点。 (即使某些人没有正确登出,显示一些额外的在线用户也不会造成太大的伤害)
现在,对于聊天应用程序,要检查用户是否仍在线,您必须使用ajax。 没有其他办法。当然,总会有一个黑客,我不知道。 看到图像 当你在这里回答(stackoverflow)。它会不断检查时间是否过去了(并且你输入了新的东西)并保存了一份副本。
您似乎最关心性能,并且您已经(大多数情况下)了解了实现细节。 只需将处理会话的表的类型更改为“内存”,这将降低为每个请求查询数据库的性能成本几乎为零,因为您直接从RAM获取数据。 只需确保每次用户明确注销时删除会话,或者将用户标记为非活动状态。
但无论你做什么,实现需要客户端和服务器之间持续通信的东西永远不能通过HTTP完美地完成。 但是,如果你提出合理的超时等,它将在99%的时间内工作。
我迟到了这个派对,但是让我给我两分钱。
在这种特定情况下,不需要针对错误通知的推送系统。 也没有必要使用cron。 让我解释 :
假设A,B和C在聊天室中且B的浏览器崩溃,因此他的会话到期。 现在,服务器认为B仍在那里,但她不是。 你如何更新A&C? 当A&C ASK进行更新时。 检查B的最后一个keepalive时间戳,并确定他们的会话已过期。
如果所有的A,B和C都崩溃了,那么这种情况永远不会发生,我听到你问。 谁在乎? 现在没有人看到我们的错误! 唯一的缺点是保持他们的聊天室活着,这需要花费一些数据库空间。 这可以在创建另一个聊天会话时清除。
最后的要点:
在用户的情况下,这将记录它们。 在聊天室的情况下,这将是那些已经过期的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.