You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用ignore_user_abort()和connection_aborted()时SSE连接无法断开

PHP SSE无法检测客户端连接断开的解决方案

问题核心

在Apache环境下实现PHP SSE持久连接时,connection_aborted()和connection_status()始终无法识别客户端(浏览器标签关闭/进程终止)的断开操作,尝试清理输出缓冲、修改php.ini配置、客户端主动调用source.close()均无效。

根本原因

PHP的连接状态检测函数仅在尝试向客户端输出数据时才会触发TCP连接状态检查。若循环中仅执行sleep而无输出操作,PHP不会主动感知客户端断开;同时Apache或中间代理的输出缓冲会延迟数据发送,进一步阻塞连接检测逻辑。

可行解决方案

1. 强制触发连接检测(核心修改)

在循环中定期发送SSE格式的空注释(不会触发客户端业务逻辑),强制PHP尝试向客户端发送数据,此时若连接已断开,connection_aborted()会返回true。

2. 优化输出缓冲配置

禁用所有层面的输出缓冲,确保数据即时发送到客户端,避免连接检测延迟。

修改后的服务端代码

<?php
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
header('X-Accel-Buffering: no'); // 禁用代理/服务器端缓冲
ignore_user_abort(true);
ob_implicit_flush(true); // 自动刷新输出,无需手动调用flush()
ob_end_clean(); // 清理初始输出缓冲

while (true) {
    // 发送空注释触发连接检测
    echo ": keep-alive ping\n\n";
    
    // 检测连接状态
    if (connection_aborted()) {
        file_put_contents("/tmp/test", "客户端连接已断开");
        exit();
    }

    // 发送实际业务数据
    $time = date('r');
    echo "data: 当前服务器时间: {$time}\n\n";
    
    sleep(5); // 适当延长间隔,减少资源消耗
}
?>

客户端优化(主动关闭连接)

在页面卸载时主动调用source.close(),帮助服务器更快感知连接断开:

<!DOCTYPE html>
<html>
<body>
<h1>获取服务器实时更新</h1>
<div id="result"></div>

<script>
if(typeof(EventSource) !== "undefined") {
  var source = new EventSource("demo_sse.php");
  source.onmessage = function(event) {
    document.getElementById("result").innerHTML += event.data + "<br>";
  };

  // 页面卸载时主动关闭SSE连接
  window.addEventListener('beforeunload', function() {
    source.close();
  });
} else {
  document.getElementById("result").innerHTML = "抱歉,你的浏览器不支持Server-Sent Events...";
}
</script>
</body>
</html>

额外注意事项

  • Apache MPM模式:推荐使用worker或event模式,prefork模式下进程隔离可能导致连接状态检测延迟。
  • TCP超时限制:若客户端异常关闭(如直接杀死进程),TCP连接可能需要数分钟才会触发超时,无法做到实时检测,定期发送ping包是最优方案。
  • 资源消耗:避免过短的sleep间隔,防止服务器进程被大量占用,建议间隔3-10秒。

内容的提问来源于stack exchange,提问作者quickblueblur

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 19:04:54