我正在尝试使用php和jquery制作一个理论上的网络聊天应用程序,我已经阅读了长轮询和 http 流,并且我设法应用了文章中介绍的大多数原则。但是,有两件事我仍然无法理解。
长轮询
- 服务器如何知道何时发送了更新?是否需要不断查询数据库还是有更好的方法?
使用 HTTP 流
- 如何在 Ajax 连接仍处于活动状态时检查结果?我知道 jQuery 的
success
ajax 调用功能,但是如何在连接仍在进行时检查数据?
我将不胜感激任何和所有的答案,在此先感谢。
是的,类似彗星的技术通常在一开始就炸毁大脑——只是让你以不同的方式思考。另一个问题是 PHP 可用的资源并不多,因为每个人都在 node.js、Python、Java 等中使用 Comet。
我将尝试回答您的问题,希望它可以为人们阐明这个话题。
服务器如何知道何时发送了更新?是否需要不断查询数据库还是有更好的方法?
答案是:在最一般的情况下,您应该使用消息队列 (MQ)。RabbitMQ 或 Redis 存储中内置的 Pub/Sub 功能可能是一个不错的选择,尽管市场上有许多竞争解决方案,例如 ZeroMQ、Beanstalkd 等。
因此,您可以订阅一个 MQ 事件并挂起,直到其他人发布您订阅的消息,MQ 会唤醒您并发送消息,而不是连续查询您的数据库。聊天应用程序是理解此功能的一个非常好的用例。
另外我必须提到,如果您要搜索其他语言的 Comet-chat 实现,您可能会注意到不使用 MQ 的简单实现。那么他们如何交换信息呢?问题是这样的解决方案通常被实现为独立的单线程异步服务器,因此它们可以将所有连接存储在线程本地数组(或类似的东西)中,在一个循环中处理多个连接,并在需要时选择一个并通知。这种异步服务器实现是一种非常适合 Comet-technique 的现代方法。但是,您很可能在 mod_php 或 FastCGI 之上实现 Comet,在这种情况下,这种简单的方法不适合您,您应该使用 MQ。
这对于理解如何实现独立的异步 Comet 服务器以在单个线程中处理多个连接仍然非常有用。最新版本的 PHP 支持 Libevent 和 Socket Streams,因此也可以在 PHP 中实现这种服务器。PHP 文档中还提供了一个示例。
如何在 Ajax 连接仍处于活动状态时检查结果?我知道 jQuery 对 ajax 调用的成功功能,但是如何在连接仍在进行时检查数据?
如果您使用普通的 Ajax 技术(如普通 XHR、jQuery Ajax 等)进行长时间运行的轮询,那么您没有一种简单的方法可以在单个 Ajax 请求中传输多个响应。正如您所提到的,您只有“成功”处理程序来处理整个响应,而不是它的一部分。作为一种解决方法,人们每个请求只发送一个响应并在“成功”处理程序中处理它,之后他们只是打开一个新的长轮询请求。这就是 HTTP 协议的工作原理。
还应该提到的是,实际上有一些解决方法可以使用各种技术来实现类似流式传输的功能,这些技术使用诸如隐藏中的无限长页面IFRAME
或使用多部分 HTTP 响应等技术。这两种方法都有一定的缺点(前一种被认为是不可靠的,有时可能会产生不必要的浏览器行为,例如无限加载指示器,而后一种会泄漏一致且直接的跨浏览器支持,但是已知某些应用程序仍然成功地依赖它当浏览器无法正确处理多部分响应时,机制会退回到长轮询)。
如果您想以可靠的方式处理每个请求/连接的多个响应,您应该考虑使用更先进的技术,例如 WebSocket,它受最新浏览器或任何支持原始套接字的平台(例如 Flash 或例如,如果您为移动应用程序开发)。
您能否详细说明消息队列?
消息队列是一个描述观察者模式(也称为“发布/订阅”或简称为 PubSub)的独立(或内置)实现的术语。如果您开发一个大型应用程序,拥有一个非常有用 - 它允许您解耦系统的不同部分,实现事件驱动的异步设计并使您的生活更加轻松,尤其是在异构系统中。它对现实世界的系统有很多应用,我只提几个:
我希望我的插图易于理解,但是消息队列是一个非常广泛的主题,因此请参阅上面提到的资源以进一步阅读。
如何在 Ajax 连接仍处于活动状态时检查结果?我知道 jQuery 对 ajax 调用的成功功能,但是如何在连接仍在进行时检查数据?
事实上,你可以。我已经为上述内容提供了修改后的答案,但我不知道它是否仍处于待处理状态或已被忽略。在此处提供更新,以便提供正确的信息。
如果您保持客户端和服务器之间的连接打开,则可以推送附加到响应的更新。随着每次更新的到来,XMLHttpRequest.onreadystatechange
事件被触发并且 的值为XMLHttpRequest.readyState
3。这意味着 XMLHttpRequest.responseText 继续增长。
你可以在这里看到一个例子:http: //www.leggetter.co.uk/stackoverflow/7213549/
要查看 JS 代码,只需查看源代码。PHP代码是:
<?php
$updates = $_GET['updates'];
if(!$updates) {
$updates = 100;
}
header('Content-type: text/plain');
echo str_pad('PADDING', 2048, '|PADDING'); // initial buffer required
$sleep_time = 1;
$count = 0;
$update_suffix = 'Just keep streaming, streaming, streaming. Just keep streaming.';
while($count < 100) {
$message = $count . ' >> ' . $update_suffix;
echo($message);
flush();
$count = $count + 1;
sleep($sleep_time);
}
?>
在基于 Gecko 的浏览器(例如 Firefox)中,可以responseText
使用multipart/x-mixed-replace
. 我没有提供这方面的例子。
看起来不可能使用jQuery.ajax
. 每当触发事件时,success
回调都不会onreadystatechange
触发。这是令人惊讶的,因为文档指出:
然而,没有提供 onreadystatechange 机制,因为 success、error、complete 和 statusCode 涵盖了所有可能的需求。
所以除非我误解了文档,否则文档可能是错误的?
您可以在这里看到一个尝试使用 jQuery 的示例:http: //www.leggetter.co.uk/stackoverflow/7213549/jquery.html
如果您查看 Firebug 或 Chrome 开发人员工具中的网络选项卡,您会看到文件大小在stream.php
增长,但success
回调仍然没有触发。