【问题标题】:PHP SSE script does not die when client exit客户端退出时PHP SSE脚本不会死
【发布时间】:2018-08-21 19:19:43
【问题描述】:

我在 PHP/jQuery 中使用服务器端事件。这是客户端:

var evtSource = new EventSource("testsse.php");
        evtSource.onmessage = function(e) {
           // DO SOMETHING WITH e
        }

这是服务器端文件:testse.php

header("Content-Type: text/event-stream\n\n");
while (1) {
  echo "message";  
  ob_flush();
  flush();
  sleep(1);
}

它工作正常,但是当客户端关闭浏览器或断开连接时,testse.php 继续运行。我的问题是我们很快就会有许多正在运行的脚本使服务器超载。我已经阅读了以下问题:

我已经阅读了以下问题:

最后一个很有趣,但最后是服务器告诉客户端这是结束了。在我们的例子中,我们希望脚本在客户端关闭时自动消失。一种解决方案是在选项卡或浏览器关闭时触发事件 (Detect browser or tab closing)。但不幸的是,众所周知,这种解决方案是不可靠的。在我看来,这不是一个“专业”的选择。

有没有办法在客户端退出时正确终止服务器端脚本?

【问题讨论】:

  • 是的,正如我所提到的,我已经阅读了这个解决方案。但是我无法访问服务器上的apache配置。
  • 您在编辑问题后提到了这一点。
  • 可以在 PHP 中使用多线程,可以使用套接字和可靠的socket_select() 函数。您不必为每个连接运行一个 PHP 脚本。让一个脚本处理多个连接。
  • 您的 PHP 脚本是否作为 Apache 模块运行?如果没有,它是如何启动的?

标签: javascript php jquery server-sent-events


【解决方案1】:

最简单的解决方案是让脚本timeout 并使用内置的retry 方法。

这意味着连接会定期关闭,如果用户还在,将从前端重新启动连接。

html5rocks.com 在 SSE here 上有一个很好的教程。

一些伪代码来说明我的意思

JavaScript 代码

var evtSource = new EventSource("testsse.php");
evtSource.onmessage = function(e) {
  // DO SOMETHING WITH e
}

PHP 代码

header("Content-Type: text/event-stream\n\n");

//Live for 60 seconds
set_time_limit(60);

//Set retry to ~1/60 second
echo "retry: 16\n\n";
ob_flush();
flush();

//Run your loop
//It will die in 60
while (1) {
  echo "message";  
  ob_flush();
  flush();
  sleep(1);
}

【讨论】:

  • 这种方法有一个严重的问题:你的 SSE 脚本会在处理 60 秒后死掉,即使客户端仍然连接。 (好吧,“严重”可能言过其实,因为 SSE 协议意味着浏览器会检测到这一点并自动重新连接。)
  • @DarrenCook 这是正确的,但只有当您依赖某些服务器端状态时才是真正的问题,在这种情况下,您必须找到一种方法来“告诉”SSE 线程用户仍然在这里。一个简单的解决方案是从前端定期调用一个单独的 heartbeat 方法(每 40 秒 AJAX 应该没问题),并让服务器以 SSE 线程可访问的方式保存时间戳(数据库或 $_SESSION似乎是最明显的选择)。然后,您可以在 SSE 线程循环中对此进行测试,并使用 set_time_limit 延长剩余时间。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-27
  • 2016-03-28
  • 1970-01-01
  • 1970-01-01
  • 2014-12-06
  • 1970-01-01
相关资源
最近更新 更多