我正在使用Ajax为我的网站构建简单的支持聊天。我想检查我当前正在聊天的用户是否离开了浏览器。
目前我通过在客户端设置间隔功能来构建该功能,该功能创建名称为userId.txt
在管理区域中,我创建了一个间隔函数,用于检查userId.txt
是否存在。如果存在,则删除它。如果自定义间隔函数未重新创建文件 - 下次admin函数将发现该文件不存在时,则将此userId
标记为不活动的客户。
抽象表示:
customer -> interval Ajax function -> php [if no file - create a new file]
admin -> interval Ajax function -> php [if file exists - delete the file] -> return state to Ajax function and do something
我想知道是否有更好的方法来实现您能想到的这个功能?
答案 0 :(得分:14)
我的解决方案是使用jquery
ready和beforeunload方法触发ajax
post
请求,该请求将在用户到达和离开时通知。
此解决方案是“ light ”,因为它每个用户只记录两次。
<强>的support.html 强>
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script>
//log user that just arrived - Page loaded
$(document).ready(function() {
$.ajax({
type: 'POST',
url: 'log.php',
async:false,
data: {userlog:"userid arrived"}
});
});
//log user that is about to leave - window/tab will be closed.
$(window).bind('beforeunload', function(){
$.ajax({
type: 'POST',
url: 'log.php',
async:false,
data: {userlog:"userid left"}
});
});
</script>
</head>
<body>
<h2>Your support html code...</h2>
</body>
</html>
<强> log.php 强>
<?php
//code this script in a way that you get notified in real time
//in this case, I just log to a txt file
$userLog = $_POST['userlog'];
file_put_contents("userlog.txt", $userLog."\n", FILE_APPEND );
//userid arrived
//userid left
备注:强>
1 - 在Chrome
,FF
和Opera
上进行了测试。我没有mac,所以我无法在Safari
上测试它,但它也应该有效
2 - 我尝试了unload方法,但它不如beforeunload
可靠
3 - 在async
请求上设置false
到ajax
意味着您要调用的语句必须在下一个语句之前完成,这可确保您在窗口/选项卡之前得到通知关闭了。
答案 1 :(得分:5)
@Gonzalon提出了一个很好的观点,但使用普通的数据库表或文件系统不断更新用户移动对于大多数硬盘来说都是穷举。这是在PHP中使用 shared memory 函数的一个很好的理由。
答案 2 :(得分:5)
您必须区分原始问题“我如何实时登记,如果用户已登录?”并且“如果用户仍然在另一边(在我的聊天中),我怎么能确定?”。
对于“登录系统”,我建议使用PHP会话。
对于“仍然存在用户”的问题,我建议更新名为LAST_ACTIVITY
的活动会话的一个字段。有必要将与客户端的最后一次联系的时间戳写入存储(数据库)并测试是否早于X秒。
我建议会话,因为你没有在你的问题中提到它们,看起来你在每个Ajax请求上手动创建userID.txt文件,对吧?这是不需要的,除非工作cookie和无会话是一个开发要求。
现在,对于PHP会话,我只需将会话处理程序(后端)更改为适合您的任何比例以及使请求信息变得容易的原因。 默认情况下,PHP使用会话临时文件夹来创建会话文件, 但您可以更改它,以便底层会话处理程序成为mariadb数据库或memcache或rediska。
当用户会话存储到数据库中时,您可以查询它们:“现在有多少用户登录?”,“谁在哪里?”。
答案为“如果用户登录,我如何实时查看?”是,在创建用户会话并成功验证用户时。
对于实时聊天应用程序,有很多技术,从“php comet”,“html5 eventsource”+“websockets”/“long polling”到“message queues”,如RabbitMq / ActiveMq with publish /订阅特定频道。
如果这是一个简单或受限制的环境,也许是VPS,那么您仍然可以坚持使用间隔Ajax请求的解决方案。然后,每个请求都可以使用服务器端时间戳更新$_SESSION['LAST_ACTIVITY']
。引用:https://stackoverflow.com/a/1270960/1163786
对此想法的修改是在鼠标移动停止时停止执行Ajax请求。如果用户未在页面上移动鼠标(例如10分钟),则会停止更新LAST_ACTIVITY时间戳。这将解决显示闲置用户在线的问题。
另一种修改是通过使用小的GET或HEADER请求来减少服务器的“仍然在这里”请求的大小。一个简短的HEADER“ping”通常就足够了,而不是通过POST发送长消息或JSON。
您可以在此处找到完整的“如何使用PHP创建Ajax Web聊天,jQuery”。他们使用15秒的超时时间进行聊天。
答案 3 :(得分:4)
你可以这样做,但它会变得缓慢,低效,而且可能非常不安全。使用数据库将是一个显着的改进,但即使这样也不会特别可扩展,这取决于&#34;实时&#34;你想要这个以及你希望它能够同时处理多少个对话。
使用像Redis这样的NoSQL解决方案,您需要经常运行的任何操作(例如:&#34;用户在线&#34;检查,存储短信术语对话更新,并在短时间间隔内检查对话更新。
然后,您可以使用数据库执行更长期的任务,例如定期存储用户信息和保存活动对话(例如,每分钟一次)。
答案 4 :(得分:4)
为什么选择Ajax而不是Websockets?肯定会有一个websocket会给你一个相当快的聊天系统,不需要生成和检查文本文件,也不会涉及数据库查找,你可以立即判断连接是否被删除。
答案 5 :(得分:4)
我会安装https://github.com/nrk/predis库。因此,在用户进行身份验证时,它会向Redis服务器发布消息。
然后你可以在后端设置一个小节点服务器 - 这很简单:
var server = require('http').Server();
var io = require('socket.io')(server);
var Redis = require('ioredis');
var redis = new Redis();
var authenticatedUsers = [];
// Subscribe to the authenticatedUsers channel in Redis
redis.subscribe('authenticatedUsers');
// Logic for what to do when a message is received from Redis
redis.on('message', function(channel, message) {
authenticatedUsers.push(message);
io.emit('userAuthenticated', message);
});
// What happens when a client connects
io.on('connection', function(socket) {
console.log('connection', socket.id);
socket.on('disconnect', function(a) {
console.log('user disconnected', a);
});
});
server.listen(3000);
远非完整,但有些东西可以帮助你开始。
或者,看一下Firebase。 https://www.firebase.com/如果你不想打扰服务器端
答案 6 :(得分:3)
我建议在构建的HTML5会话存储中使用它。所有现代浏览器都支持此功能,因此我们不会遇到相同的问题。
这将有助于我们高效快速地识别用户是否在线。每当用户移动鼠标或按键时,会更新会话存储的日期和时间。定期检查它是否为空或空,并决定用户离开网站。
答案 7 :(得分:3)
使用cookie的好处是
,而不是创建和删除文件,你可以做同样的事情答案 8 :(得分:3)
根据您的资源,您可以选择 websockets 或之前名为长池请求的方法。两者都确保服务器和客户端之间的双向通信。但它们的资源可能很昂贵。
这是关于websocket的一个很好的教程:
答案 9 :(得分:3)
我会使用你(管理员)可以触发的回调。我在Web应用程序和移动应用程序中使用此技术(所有这些都在服务器的用户端设置):
Web应用程序的回调通常使用JavaScript,您可以定义用户何时以及如何打电话回家。将其视为服务渠道。
答案 10 :(得分:2)
如果它是aspnet我会说signalR ...但是对于php或许你可以查看Rachet它可能对你想要完成的很多东西有所帮助,因为消息可以推送到客户端而不是客户投票。
答案 11 :(得分:2)
这个想法很简单。服务器知道用户是否已连接。他可以发送类似&#34;嘿,用户xyz仍然登录&#34;或者&#34;嘿,用户xzy似乎不再登录了#34;并且客户端仅侦听该消息并且可以对消息做出反应(例如,通过JavaScript)。
优点是:SSE非常适合实时应用程序,因为服务器只需要发送数据而客户端只需要监听,另请参阅specification。
如果您确实需要双向通信,或者不能使用规范中提到的两个依赖项,那么当然不是使用SSE的最佳决策。
这是延迟更新,其中包含一个不错的chat example (written in Java)。也许了解如何在PHP中实现它也很好。