【问题标题】:How to get events instantly using SSE?如何使用 SSE 立即获取事件?
【发布时间】:2022-08-23 01:29:38
【问题描述】:

我目前正在尝试使用 PHP 使用服务器发送的事件,但它们不会在浏览器上立即触发。

这是我的代码:


<?php
    
    // Headers must be processed line by line.
    header(\'Content-Type: text/event-stream\');
    header(\'Cache-Control: no-cache\');
    header(\'X-Accel-Buffering: no\');
    while(true)
    {
    
        // Set data line
        echo \"event: server-time\";
        echo \"data: \" . date( \'G:H:s\', time() );
        //echo str_repeat(\" \", 4096);
    
        ob_end_flush();     // Strange behaviour, will not work
        flush();            // Unless both are called !
    
        // Wait one second.
        sleep(1);

}

虽然它有效,但似乎缓冲区刷新并将数据发送到浏览器的最小大小。事实上,如果我取消注释 str_repeat 行,我会得到几乎瞬时的事件(例如,每秒一个)。但是,如果我保持评论,浏览器会持续加载大约 2 分钟,然后发送过去 2 分钟的所有数据。

我在 Stack Overflow 上环顾四周,但找不到适用于所有问题的答案。

以下是来自phpinfo() 的一些信息,我觉得在这种情况下很有用,请不要犹豫,询问更多信息:

PHPINFO

Name Value
Server API FPM/FastCGI
PHP Version  7.4.30
BZip2 Support  Enabled
Registered PHP Streams https, ftps, compress.zlib, compress.bzip2, php, file, glob, data, http, ftp, phar, ssh2.shell, ssh2.exec, ssh2.tunnel, ssh2.scp, ssh2.sftp, zip
Registered Stream Socket Transports  tcp, udp, unix, udg, ssl, tls, tlsv1.0, tlsv1.1, tlsv1.2, tlsv1.3
Registered Stream Filters zlib., bzip2., convert.iconv., string.rot13, string.toupper, string.tolower, string.strip_tags, convert., consumed, dechunk, mcrypt., mdecrypt., http.*
 Stream Wrapper support compress.bzip2://
 Stream Filter support  bzip2.decompress, bzip2.compress
BZip2 Version 1.0.6, 6-Sept-2010
output_buffering  no value
output_encoding no value
output_handler no value
zlib.output_compression Off
zlib.output_compression_level  -1
zlib.output_handler no value

    标签: php server-sent-events event-stream


    【解决方案1】:

    ob_flush() 用于 PHP 自己的缓冲区(这就是它首先出现的原因),flush() 应该刷新 Web 服务器缓存。所以你的代码是正确的。我认为您遇到的问题是由于您使用“FPM/FastCGI”

    我在手册中找到了this comment

    如果您想在使用 Apache httpd 中的 php-fpm 和 mod_proxy_fcgi 时进行刷新,从 2.4.31 开始,您可以附加 flushpackets=on 以启用刷新,

    这个页面有一些建议:https://serverfault.com/q/488767(注意,它们都比上面的手动评论更老。)

    或者,如果没有绑定到 FastCGI,另一种解决方案是切换到 Apache 的 PHP 模块,flush() 肯定可以工作。

    【讨论】:

      【解决方案2】:

      我不知道为什么人们在 SSE 代码中使用 while 循环。 它不会挂起您的浏览器吗?

      <?php
          // Headers must be processed line by line.
          header('Content-Type: text/event-stream');
          header('Cache-Control: no-cache');
          header('X-Accel-Buffering: no');
          // Set data line
          $events = "";
          $events .= "event: server-time\ndata: " . date('G:H:s', time()) . "\n\n"
      
          //Append other events with logic
      
          echo $event;
      

      【讨论】:

        猜你喜欢
        • 2011-11-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-08-30
        • 1970-01-01
        • 2020-08-26
        • 1970-01-01
        • 2012-03-22
        相关资源
        最近更新 更多