Home  >  Article  >  Backend Development  >  http browser actively disconnects and php actively disconnects

http browser actively disconnects and php actively disconnects

不言
不言Original
2018-04-26 14:41:215038browse

This article shares with you the http browser actively disconnecting and php actively disconnecting. Friends who are interested can take a look

Abstract: The cause of the incident is because of the usual encounters during development doubts. Once, after the browser client actively disconnected, it was found that the server-side php script was still executing, so I didn't know how to stop the script. Another time, there was a need to have the php script actively disconnect, and then the subsequent scripts continued to execute (a time-consuming task), so this blog was created.

1. The browser proactively disconnects

Under the commonly used LAMP combination, we believe that the browser accesses a php script, the script starts executing, the script outputs content, and ends running, apache In response to http, the browser receives the http response and displays the result.
 Let’s consider special situations.
  1. The browser sends an http request, and PHP performs a time-consuming task (20s) (assuming PHP's set_time_limit is set to 30s). During this period, the browser does not respond and the user clicks the browser X, the browser actively disconnects, does the php script continue to run?
 Suppose the time-consuming task is: calculate fib(25), the browser test response takes 1.15s, each time the time-consuming task is executed, the file Log is written once, the time-consuming task is executed 10 times, and after the fifth execution At this time, the client actively disconnects and observes the situation.
The code is as follows:

<?phpfor ($i=0; $i < 10; $i++) { 
    fib(25);
    setLog(date(&#39;H:i:s&#39;));
}function fib($n = 3){
    if($n == 0){        return 1;
    }    if($n == 1){        return 1;
    }    return fib($n - 1) + fib($n -2);
}function setLog( $massage, $path=&#39;&#39;){
    $log_path = empty($path)?&#39;./log_&#39;.date(&#39;Y-m-d&#39;).&#39;.log&#39;:$path;    $time = date(&#39;Y-m-d H:i:s&#39;);    $error_page = &#39;http://&#39; . $_SERVER[&#39;HTTP_HOST&#39;] . $_SERVER[&#39;REQUEST_URI&#39;];
    file_put_contents($log_path, "LOG TIME:".$time.PHP_EOL, FILE_APPEND);
    file_put_contents($log_path, "LOG URL:".$error_page.PHP_EOL, FILE_APPEND);    if(is_array($massage)){        $massage = json_encode($massage);
    }
    file_put_contents($log_path, "LOG MESSAGE:".$massage.PHP_EOL.PHP_EOL, FILE_APPEND);
}?>

 The browser disconnected when execution reached 5.44s.
 The log shows: The script has been executed for 10 cycles.
 This is different from what we thought before;

  2. Optimize it. I saw it said on the Internet that PHP determines whether the client connection is disconnected when PHP outputs content to the client. The judgment is , then we modify the test code:

<phpfor ($i=0; $i < 10; $i++) { 
    fib(25);    setLog(date(&#39;H:i:s&#39;));    echo "hello";
}

//这里省略了fib和setLog函数
?>

 Test again and find that the results are the same as the last test. The reason: when php outputs content to the client, there are three buffering stages, which are:
php buffer => web server buffer => browser buffer
Only when the buffer is full It will be output to the client. This is actually the principle of the back-end outputting content to the front-end every once in a while. Of course, you can also control the output to the client when the buffer is not full.

#3. Modify the test code again to make the content of the output client large enough: Instead of the previous demo, the script needs to be completely executed before the content is output to the client. At the same time, the client connection is closed at this time. When the server outputs content to the client again, it will check that the client connection has been disconnected. At this time, the script will stop running. This is the test result we want.

 

4. Modify the test code again. This time, instead of outputting a large amount of content at a time, the content of the buffer is deliberately manipulated, so that although the content is not enough to be output from the buffer to the client, it is output to the client in advance. client.

Test code:

<?php$re = "";for($i=0; $i < 10000; $i++){    $re .= "aa";
}for ($i=0; $i < 10; $i++) { 
    fib(25);
    setLog(date(&#39;H:i:s&#39;));    echo $re;
}//这里省略了fib和setLog函数?>
Summary:

In principle, the client actively disconnects and the php script stops running;
  • But the premise is that PHP knows how the client disconnects. Only when PHP outputs content to the client (not the PHP buffer, not the web server buffer) will PHP know that the client connection is interrupted. , it will stop running;
  • There are two ways for php to output content to the client. One is to fill the content into the buffer and automatically send it to the client; the other is to use ob_flush, the flush function to actively flush the buffer content to the client;
  • php script operation is also subject to internal The script timer limit can be configured in php.ini or the host apache configuration file, or set through the set_time_limt function in the script;
  • When the client actively disconnects, the php script When it does not stop running, it is also limited by the script timer;
  • When the php script sets ignore_user_abort(true); then even if the client connection is disconnected, php outputs the content to the client Even if the client knows that the client connection is disconnected, it will not stop the script execution;
  • #Internally, the connection status maintained by the system can be checked through the return value of the function connection_status, 0: normal; 1: aborted (disconnected); 2: timeout; The detection of changed status also requires the PHP script to output the content to the client to know, otherwise it will always be 0;
  • In addition, there are There is a function that can also detect whether the client connection is disconnected (connection_aborted), 0 is normal, 1 is disconnected.
  • A strange problem is that when the client connection has been disconnected and the php script outputs twice, the status bit becomes 1;
  • 2. PHP server actively disconnects
To make PHP actively disconnect, use the two fields content-length and connection in the http response header. The meanings are:

content-length, when the client receives the response header content-length, when the corresponding body receives the specified size, it will disconnect from the server;
  • connection,当客户端收到响应头connection的值为close或者keep-alive,决定关闭当前tcp连接或者继续使用当前连接作下一次请求;

  • 测试发现,当只指定conetent-length的时候也能达到php主动断开连接;

  • 其实说是php主动断开连接,其实是php通知客户端主动断开的连接;

示例代码:

<?phpecho "hello world";

test();for ($i=0; $i < 10; $i++) { 
    fib(25);
    setLog(date(&#39;H:i:s&#39;));
}function test(){
    $size = ob_get_length();
    header("content-length:" . $size);    //header("connection:close");
    ob_flush();
    flush();
}//这里省略了fib和setLog函数?>



ba33df4ef3efea3726e09756c08771e7



The above is the detailed content of http browser actively disconnects and php actively disconnects. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn