1

我正在尝试在 php 上学习服务器端事件。

起初,几乎每个示例在服务器端都有一个循环,并使用 ob_flush()/flush() 返回值。所以我试着这样做:

<?php

  header('Content-Type: text/event-stream');
  header('Cache-Control: no-cache');

  // Output a 'waiting message'
  $progress = 0;

  while ($progress < 100) {
     echo 'data:';
     echo $progress;
     echo "\n\n";
     flush();
     ob_flush(); //I tried ob_implicit_flush(true) too
     $progress++;
     sleep(1);
  }

?>

和 javascript :

   function start(btn) {    

     var source = new EventSource('/fix/streamingGet.php');

     source.onmessage = function(e) {
         console.log(e.data);
     };

   }

但是在脚本结束之前什么都没有收到......所以我最终尝试没有无限循环并且一切正常

<?php

      header('Content-Type: text/event-stream');
      header('Cache-Control: no-cache');

      // Output a 'waiting message'
      echo 'data:';
      echo rand(5, 15);
      echo "\n\n";

?>

编辑:没关系,我之前可能在某个地方犯了一个错误,因为现在它可以工作了

编辑:我的意思是使用 ob_flush/flush 返回多个结果的循环(不是无限循环,我的错)

但是我是否需要通过多次刷新来返回我的数据以获得服务器端事件的性能?

更新 :

从我的测试和研究来看,似乎 php 不允许多个会话,这使得第一个示例阻止对服务器的任何其他调用。因此,唯一有效的 php 解决方案似乎每次都返回值。我认为这与对服务器进行多次定时 ajax 调用是一样的。

我猜如果我真的想从服务器流式传输一个值,那么我可能应该在我的 web 应用程序一侧使用 nodejs。

4

1 回答 1

1

你所做的基本上是正确的。

但是放在ob_flush()before flush()(因为ob_flush()将 PHP 缓冲区刷新到 Apache,然后flush()告诉 Apache 将缓冲的内容发送到客户端)并且放在@before更健壮ob_flush()(因为如果您关闭了 PHP 缓冲,您可能会收到一条错误消息 -@抑制它)。

(关于在 PHP 中使用无限循环的注释是错误的:在这种情况下它们很好。当浏览器客户端断开连接时,Apache 将终止 PHP 实例。运行无限/长时间运行的循环不会导致内存泄漏。)

PHP 会话锁定。因此,如果同一用户(同一会话)可能在 SSE 脚本发送数据时访问您网站的其他部分,则您需要 SSE 脚本停止使用会话。因此,从脚本顶部的会话中获取所需的任何数据,然后session_write_close()在进入主循环之前调用。见https://stackoverflow.com/a/19440378/841830

于 2018-03-29T08:02:59.937 回答