【问题标题】:How to display HTML to the browser incrementally over a long period of time?如何在很长一段时间内逐步向浏览器显示 HTML?
【发布时间】:2010-10-30 23:41:32
【问题描述】:

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

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

【问题讨论】:

    标签: php xmlhttprequest comet


    【解决方案1】:

    Long polling 是执行此类操作的常用技术;简单总结一下,它的工作原理如下:

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

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

    3. 返回 1)

    这就是 Facebook implements its chat feature

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

    【讨论】:

    • 这就是我一直在寻找的,尽管问题的标题被弄乱了。
    • 它当然适用于 Facebook - 通知、聊天和许多其他功能都使用这种方法。
    • 请记住 Facebook 在后端使用 Erlang 来处理聊天,因此它可以管理所有打开的连接。 Apache/PHP 永远无法扩展那么高。
    【解决方案2】:

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

    因此,您只需定期发送少量数据以避免超时。

    【讨论】:

      【解决方案3】:

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

      【讨论】:

      • 在发布我的帖子后,我看到了这个。绝对是更好的答案。您可以只拥有一个 DIV,您可以使用 JavaScript 不断填充一些 AJAX 内容。
      • 轮询对于像聊天这样的事情来说是一个非常糟糕的解决方案,其中的暂停可能会有很大的不同,并且您希望快速出现响应,但同时避免频繁地轮询数千个轮询给您的服务器带来负担大多数时候不返回任何东西的客户。将 HTTP 协议用于它并非设计用于工作的东西,并且在这种情况下是更好的解决方案。
      【解决方案4】:

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

      echo "<HTML><HEAD.../HEAD><BODY>";
      while (running)
      {
          echo "printing html... </br>";
      }
      echo "</BODY></HTML>";  //all done
      

      【讨论】:

        【解决方案5】:

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

        所有这些技术都只是 hack,http 并不是为此而设计的。

        【讨论】:

          【解决方案6】:

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

          【讨论】:

            【解决方案7】:

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

            【讨论】:

              【解决方案8】:

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

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2010-10-18
                • 1970-01-01
                • 2017-09-16
                • 1970-01-01
                • 2012-01-15
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多