【发布时间】:2010-10-30 23:41:32
【问题描述】:
我是否需要传回任何 HTTP 标头以告诉浏览器我的服务器不会立即关闭连接并在收到 HTML 时显示?是否有必要让 HTML 像 flush() 那样增量显示?
这种技术曾经用于聊天之类的事情,但我正在考虑将其用于 COMET 类型的应用程序。
【问题讨论】:
标签: php xmlhttprequest comet
我是否需要传回任何 HTTP 标头以告诉浏览器我的服务器不会立即关闭连接并在收到 HTML 时显示?是否有必要让 HTML 像 flush() 那样增量显示?
这种技术曾经用于聊天之类的事情,但我正在考虑将其用于 COMET 类型的应用程序。
【问题讨论】:
标签: php xmlhttprequest comet
Long polling 是执行此类操作的常用技术;简单总结一下,它的工作原理如下:
客户端向服务器发送 XHR。
客户端上运行的页面接收到这些数据,并对其进行处理。
这就是 Facebook implements its chat feature。
This article 还澄清了长轮询的一些误解,并详细说明了这样做的一些好处。
【讨论】:
客户端在一定时间内没有收到任何数据时会关闭连接。此超时不受 HTTP 标头的影响。它是特定于客户端的,通常设置为 120 秒 IIRC。
因此,您只需定期发送少量数据以避免超时。
【讨论】:
我认为一个更强大的解决方案是一个带有 Javascript 计时器的页面,它可以轮询服务器以获取新数据。保持响应开放并不是 HTTP 协议的设计目的。
【讨论】:
我会在执行过程中回显/打印 HTML。有几种不同的方法可以让脚本在发送下一位之前暂停。您不需要对标头或任何特殊代码做任何事情来告诉浏览器等待。只要您的脚本仍在运行,它就会呈现从脚本接收到的 HTML。
echo "<HTML><HEAD.../HEAD><BODY>";
while (running)
{
echo "printing html... </br>";
}
echo "</BODY></HTML>"; //all done
【讨论】:
永远尝试框架(如在 gmail 中)
所有这些技术都只是 hack,http 并不是为此而设计的。
【讨论】:
在脚本的末尾,使用类似这样的东西(假设您通过将 ob_start() 放在页面顶部来打开输出缓冲
<?php
set_time_limit(0); // Stop PHP from closing script after 30 seconds
ob_start();
echo str_pad('', 1024 * 1024, 'x'); // Dummy 1 megabyte string
$buffer = ob_get_clean();
while (isset($buffer[0])) {
$send = substr($buffer, 0, 1024 * 30); // Get 30kbs bytes from buffer :D
$buffer = substr($buffer, 1024 * 30); // Shorten buffer
echo $send; // Send buffer
echo '<br />'; // forces browser to reload contents some how :P
ob_flush(); // Flush output to browser
flush();
sleep(1); // Sleep for 1 second
}
?>
无论用户和服务器的连接速度有多快,该脚本基本上都会以 30kbs(模拟)输出 1 兆字节的文本。
【讨论】:
根据您正在执行的操作,您可以在脚本继续执行时回显,然后在回显时将 html 发送到浏览器。
【讨论】:
我建议您研究使用 Ajax 而不是普通的旧 HTML 来实现此类功能。这让您在架构设计和用户界面方面更加灵活
【讨论】: