当用户关闭页面时,如何阻止服务器发送的事件脚本运行?PHP


How can i stop a server sent event script from running when the user closes the page? PHP

我试图在PHP后端使用SSE向用户发送消息。

后端代码的功能部分看起来像-

<?php
set_time_limit(0);
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
ignore_user_abort(0);
@session_start();
    ob_start();
    echo "retry: 1000'n";
    ob_flush();
    flush();
    require_once 'sql_connection_class.php';
    require 'chatbox_class.php';
    $chatbox=new chatboxclass($_GET['friendid']);
    function recursivesenddata(){
    global $chatbox;
    $jsonobj=$chatbox->jsonloadunreadmessages();
    //append json object
if($jsonobj!=-1){
>           echo "data:{$jsonobj}'n'n";
>           ob_flush();
>           flush();
>         }else{
>           //don't send anything   
>         }
    }
while(true){
      recursivesenddata();
      session_write_close();
      sleep(1);
    }
?>

当用户关闭页面时,ignoreuserabort(0)似乎什么都不做。

在$chatbox->jsonloadreadmessages()中,有一个函数应该只在页面打开时执行,它会更新mySQL数据库中的内容。但是即使页面关闭,这个脚本也会继续在服务器上运行!

当用户关闭页面以退出无限while循环时,是否在服务器端进行检查?

PHP脚本应该在连接套接字关闭后立即终止。如果用户关闭页面时脚本仍在运行,那么Apache/PHP配置就出现了严重问题。

当客户端明确调用EventSource.close()、由于网络问题导致连接丢失、客户端关闭页面或PHP脚本终止时,可能会发生套接字关闭。

ignore_user_abort(false)什么也不做;这是默认行为(脚本在连接关闭时终止)。将true作为参数传递会使您的脚本在连接中幸存下来,但这并不能解决您的问题。

您的retry: 1000没有任何作用,因为您从未关闭服务器端的套接字。当客户端激活EventSource对象时,应该调用您的PHP脚本,并仅在客户端请求时终止(或者如果网络出现故障),因此无论最初的DB调整如何,每次聊天连接都应该只发生一次。这是假设客户端没有做任何会关闭连接的事情。

顺便说一句,这会给服务器带来很大的压力:在整个聊天过程中,每个聊天客户端都会运行一个PHP进程,而轮询周期大约小了10倍(10秒绰绰有余)。让客户端每隔30秒左右轮询一次新消息会减少浪费。

ignore_user_abort()在IIS系统上被忽略,您的配置可能会阻止它。

尝试在while循环中使用connection_aborted():

while ( connection_aborted() == 0 ) {
    recursivesenddata();
    session_write_close();
    sleep(1);
}