12

我是否需要传回任何 HTTP 标头来告诉浏览器我的服务器不会立即关闭连接并在收到 HTML 时显示?是否有必要让 HTML 像 flush() 那样增量显示?

这种技术曾经用于聊天之类的事情,但我正在考虑将它用于 COMET 类型的应用程序。

4

8 回答 8

14

长轮询是执行此类操作的常用技术;简而言之,它的工作原理如下:

  1. 客户端向服务器发送 XHR。

    • 如果有数据准备好,服务器会立即返回。
    • 如果没有,服务器保持连接打开,直到数据可用,然后返回。
    • 如果请求超时,请返回 1)。
  2. 客户端上运行的页面接收此数据,并对其进行处理。

  3. 回到 1)

这就是 Facebook实现其聊天功能的方式。

本文还澄清了长轮询的一些误解,并详细说明了这样做的一些好处。

于 2009-06-03T13:30:29.103 回答
2

当客户端在一定时间内没有收到任何数据时,将关闭连接。此超时不受 HTTP 标头的影响。它是特定于客户端的,通常设置为 120 秒 IIRC。

因此,您所要做的就是定期发送少量数据以避免超时。

于 2009-06-03T13:28:16.893 回答
1

我认为一个更强大的解决方案是一个带有 Javascript 计时器的页面,它可以轮询服务器以获取新数据。保持响应开放并不是 HTTP 协议的设计目的。

于 2009-06-03T13:19:29.297 回答
1

我会在我去的时候回显/打印 HTML。有几种不同的方法可以让脚本在发送下一个位之前暂停。您不需要对标头或任何特殊代码执行任何操作来告诉浏览器等待。只要您的脚本仍在运行,它就会呈现从脚本接收到的 HTML。

echo "<HTML><HEAD.../HEAD><BODY>";
while (running)
{
    echo "printing html... </br>";
}
echo "</BODY></HTML>";  //all done
于 2009-06-03T13:23:29.727 回答
1

尝试永远框架(如在 gmail 中)

所有这些技术都只是黑客,http 不是为了做到这一点而设计的。

于 2009-06-03T13:28:21.213 回答
1

在脚本的末尾,使用类似这样的东西(假设您通过将 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 兆字节的文本。

于 2009-06-03T15:16:46.847 回答
0

根据您正在执行的操作,您可以在脚本继续执行时回显,然后在回显时将 html 发送到浏览器。

于 2009-06-03T13:13:38.030 回答
0

我建议您研究使用 Ajax 而不是普通的旧 HTML 来实现此类功能。这使您在架构设计和用户界面方面具有更大的灵活性

于 2009-06-03T13:26:35.727 回答