Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/253.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在PHP中跟踪登录用户_Php_Session - Fatal编程技术网

在PHP中跟踪登录用户

在PHP中跟踪登录用户,php,session,Php,Session,我正在尝试用PHP和AJAX编写一个简单的web聊天应用程序 我需要知道所有打开的会话,这样我就可以显示可与之交谈的在线用户列表。我还需要注意注销,因为我使用“发送方和接收方都处于脱机状态”作为考虑终止聊天会话和删除消息的条件 我一直在跟踪数据库中登录的用户:在登录时添加一个条目,在注销时删除它,效果很好,但并不全面,因为用户可以通过两种其他方式注销: 服务器端会话在不活动后过期 客户端cookie在浏览器关闭时被破坏。使用某种onclose触发的AJAX似乎不是个好主意(如果浏览器崩溃了怎么

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

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

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

  • 服务器端会话在不活动后过期
  • 客户端cookie在浏览器关闭时被破坏。使用某种onclose触发的AJAX似乎不是个好主意(如果浏览器崩溃了怎么办?)
最简单的解决方案似乎是保留最后一个活动的时间戳。不过,我看到了一些问题:

  • AFAIK服务器端过期是基于机会的,所以它不准确(如果我把过期时间弄错了3分钟,那就是3分钟,有人可能会和离线用户聊天,想知道为什么没有人应答)
  • 我必须不断地查询数据库,以检查每个登录用户的上次活动时间与当前时间的比较。我看不出我什么时候/在哪里能有效地做到这一点。每次需要在线用户列表时都这样做似乎很愚蠢

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

我不确定您是否需要概率和除数,但以下是我为自动注销用户所做的:

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();

我认为您无法通过关闭浏览器、internet连接问题等来减轻不断查询以确定用户是否已注销的问题,但您可以让每个客户端每5秒向服务器发出一次AJAX请求,以更新上次活动时间,让服务器上的应用程序考虑到用户“错过了”,如果他们错过了3-4个连续请求(即,他们的最后活动时间是20秒)。
在客户端,每次客户端向另一个用户发送消息时,您都可以检查上次活动时间,如果发生这种情况,您可以回复他们已注销。如果他们试图与其他用户聊天,您也可以立即拨打电话检查他们的状态。然后,您可以每隔30秒检查用户列表中所有用户的状态。这样,如果与您聊天的人意外离线,您的客户可以很快得到反馈。

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

如果您切换到使用数据库绑定的会话处理程序,那么一切都会变得非常简单。我用谷歌快速搜索了一下,有很多例子。但其中很多人(例如)在阅读课时没有检查是否过期。我链接到的示例确实显示了将用户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)。它会不断检查时间是否已过(以及您是否键入了任何新内容)并保存副本。

您可以反转您的模式,用推送通知系统取代Ajax推送行为

通过这种方式,您可以实时通知聊天室用户新聊天室成员的登录和注销。我在实践中从未做过类似的事情,但我读过关于这种技术的文章,对于像你这样的案例来说,这似乎非常有趣

这只是比ajax拉方式稍微难一点,但是一旦实现了主结构,您就可以轻松地添加功能,并且性能会更好

我发现一些有用的链接:


这是railscast的一集,它处理javascript聊天,实现在rails中,但是即使您不了解rails,您也应该能够遵循它来获得核心概念:

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


但无论您做什么,实现一些需要客户端和服务器之间持续通信的东西都永远无法通过HTTP完美完成。但是如果你把合理的暂停时间等放进去,它会在99%的时间里起作用。

我这次聚会迟到了,但让我给我的两分钱

在这个特定场景中,不需要推送系统来处理错误通知。也不需要cron。让我解释一下:

假设A、B和C在聊天室,B的浏览器崩溃,所以他的会话过期。现在,服务器认为B还在,但她不在。您如何更新A&C?当A&C要求更新时。检查B的最后一个keepalive时间戳,并确定他们的会话