この記事では、http ブラウザーがアクティブに切断する方法と php がアクティブに切断する方法について説明します。興味のある友人は参照してください。
要約: このインシデントの原因は、開発中に発生した疑問によるものです。かつて、ブラウザ クライアントがアクティブに切断された後、サーバー側の PHP スクリプトがまだ実行されていることが判明したため、スクリプトを停止する方法がわかりませんでした。またある時は、PHP スクリプトを積極的に切断し、その後後続のスクリプトを実行し続ける必要があったため (時間のかかるタスク)、このブログが作成されました。
一般的に使用される LAMP の組み合わせでは、ブラウザが php スクリプトにアクセスし、スクリプトが実行を開始し、スクリプトがコンテンツを出力して実行を終了し、Apache が http に応答し、ブラウザが受信するものと考えられます。 http 応答すると、結果が表示されます。
特殊な状況を考えてみましょう。
1. ブラウザーは http リクエストを送信し、PHP は時間のかかるタスク (20 秒) を実行します (PHP の set_time_limit が 30 秒に設定されていると仮定します)。ユーザーが [ブラウザーを開く] をクリックしても、ブラウザーは応答しません。接続すると、PHP スクリプトは引き続き実行されます。 時間のかかるタスクが fib(25) の計算であるとします。時間のかかるタスクが実行されるたびに、ファイル ログが 10 回書き込まれます。 5 回目の実行時には、クライアントは積極的に切断して状況を観察します。
コードは以下の通りです:
<?phpfor ($i=0; $i < 10; $i++) { fib(25); setLog(date('H:i:s')); }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=''){ $log_path = empty($path)?'./log_'.date('Y-m-d').'.log':$path; $time = date('Y-m-d H:i:s'); $error_page = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']; 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); }?>
ログには次のように表示されます: スクリプトは 10 サイクルを完了しました。
これは以前考えていたものと異なります;
2. PHP がコンテンツをクライアントに出力するときにクライアント接続が切断されるかどうかを判断するということをインターネットで見たので、テストを実行します。 : <phpfor ($i=0; $i < 10; $i++) {
fib(25); setLog(date('H:i:s')); echo "hello";
}
//这里省略了fib和setLog函数
?>
バッファがいっぱいの場合のみクライアントに出力されます。これは実際にはバックエンドがコンテンツをフロントエンドに時々出力するという原則。もちろん、バッファがいっぱいでない場合に、クライアントへの出力を制御することもできます。
<?php$re = "";for($i=0; $i < 10000; $i++){ $re .= "aa";
}for ($i=0; $i < 10; $i++) {
fib(25);
setLog(date('H:i:s')); echo $re;
}//这里省略了fib和setLog函数?>
4. 再度テストコードを修正します。今回は一度に大きな内容を出力するのではなく、バッファからクライアントに出力しきれない内容を意図的に操作します。クライアントに事前に出力します。
テストコード:
for ($i=0; $i < 10; $i++) { fib(25); setLog(date('H:i:s')); echo "hello " . date('H:i:s') . "<br>"; ob_flush(); flush(); } //这里省略了fib和setLog函数
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('H:i:s')); }function test(){ $size = ob_get_length(); header("content-length:" . $size); //header("connection:close"); ob_flush(); flush(); }//这里省略了fib和setLog函数?>
<完>
以上がhttpブラウザはアクティブに切断し、phpはアクティブに切断しますの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。