如果HTTP请求被取消/关闭,PHP会自动终止脚本

asi*_*haq 7 php ajax

问题是,对于长时间的进程,无论客户端浏览器当前是否连接,PHP脚本都会继续执行.是否有可能如果客户端已终止对脚本的Ajax调用,那么脚本也会终止在服务器上?

asi*_*haq 8

正如@metadings指出的那样,php确实有一个检查名为connection_aborted()的连接中止的函数.如果连接终止,它将返回1,否则返回0.

在长服务器端进程中,用户可能需要知道客户端是否与服务器断开连接,或者他是否已关闭浏览器,然后服务器可以安全地关闭该进程.

特别是在应用程序使用php会话的情况下,如果我们在客户端断开连接后仍然运行长进程,则服务器将无法响应此会话.来自同一客户端的任何其他请求将等到早期进程完全执行.这种情况的原因是在进程运行时会话文件被锁定.但是,您可以通过调用session_write_close()方法来解锁它.但这在所有情况下都不可行,可能需要在流程结束时向会话写入内容.

现在,如果我们只在循环中调用connection_aborted(),那么无论连接是否关闭,它总是返回0.

0表示连接未中止.这是误导.但是,经过重新搜索和实验,如果发现php 中的输出缓冲区是原因.

首先,为了检查中止,循环中的开发人员必须通过回显一些文本将一些输出发送到客户端.例如:

print " ";
Run Code Online (Sandbox Code Playgroud)

由于进程仍在运行,输出将不会发送到客户端.现在要发送输出,我们需要刷新输出缓冲区.

flush ();
ob_flush ();
Run Code Online (Sandbox Code Playgroud)

然后,如果我们检查中止,那么它将给出正确的结果.

if (connection_aborted () != 0) {
  die();
}
Run Code Online (Sandbox Code Playgroud)

以下是工作示例,即使您使用的是PHP会话,这也会起作用:

session_start ();
ignore_user_abort ( TRUE );

file_put_contents ( "con-status.txt", "Process started..\n\n" );

for($i = 1; $i <= 15; $i ++) {

    print " ";

    file_put_contents ( "con-status.txt", "Running process unit $i \n", FILE_APPEND );
    sleep ( 1 );

    // Send output to client
    flush ();
    ob_flush ();

    // Check for connection abort
    if (connection_aborted () != 0) {
        file_put_contents ( "con-status.txt", "\nUser terminated the process", FILE_APPEND );
        die ();
    }

}

file_put_contents ( "con-status.txt", "\nAll units completed.",  FILE_APPEND );
Run Code Online (Sandbox Code Playgroud)

编辑07-APR-2017

如果有人在Windows上使用Fast-Cgi,那么当使用以下代码中止连接时,他实际上可以从内存中终止CGI线程:

if (connection_aborted () != 0) { apache_child_terminate(); exit; }


met*_*ngs 5

查看 PHPconnection_aborted()函数。在进行处理时,您有时可以检查中止的连接以正常取消进度,就像在交互式线程模型中所做的那样。

  • @metadings 这似乎不适用于 ajax 请求。ajax 请求被终止,connection_aborted() 仍然返回 0。即使我尝试关闭网页,脚本仍然继续执行。可能是什么原因? (3认同)