ホームページ  >  記事  >  バックエンド開発  >  httpブラウザはアクティブに切断し、phpはアクティブに切断します

httpブラウザはアクティブに切断し、phpはアクティブに切断します

不言
不言オリジナル
2018-04-26 14:41:215047ブラウズ

この記事では、http ブラウザーがアクティブに切断する方法と php がアクティブに切断する方法について説明します。興味のある友人は参照してください。

要約: このインシデントの原因は、開発中に発生した疑問によるものです。かつて、ブラウザ クライアントがアクティブに切断された後、サーバー側の PHP スクリプトがまだ実行されていることが判明したため、スクリプトを停止する方法がわかりませんでした。またある時は、PHP スクリプトを積極的に切断し、その後後続のスクリプトを実行し続ける必要があったため (時間のかかるタスク)、このブログが作成されました。

1. ブラウザが能動的に切断する

一般的に使用される 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(&#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);
}?>

実行が5.44秒に達するとブラウザが切断されました。

ログには次のように表示されます: スクリプトは 10 サイクルを完了しました。
これは以前考えていたものと異なります;

2. PHP がコンテンツをクライアントに出力するときにクライアント接続が切断されるかどうかを判断するということをインターネットで見たので、テストを実行します。 :

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

//这里省略了fib和setLog函数
?>
再度テストすると、結果は前回のテストと同じであることがわかります。理由: PHP がコンテンツをクライアントに出力するとき、次の 3 つのバッファリング段階があります:

PHP バッファ => Web サーバー バッファ => ブラウザ バッファ

バッファがいっぱいの場合のみクライアントに出力されます。これは実際にはバックエンドがコンテンツをフロントエンドに時々出力するという原則。もちろん、バッファがいっぱいでない場合に、クライアントへの出力を制御することもできます。

3. 出力クライアントのコンテンツを十分な大きさにするために、テスト コードを再度変更します。

<?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函数?>
今回もテストすると、前のデモではなく、しばらくしてからブラウザがいくつかの応答を受け取ることがわかります。これにはスクリプトが必要です。コンテンツは、完全に実行された後にのみクライアントに出力されます。同時に、この時点でクライアント接続が閉じられ、サーバーがコンテンツをクライアントに再度出力すると、この時点でクライアント接続が切断されたことが確認されます。これが私たちが望むテスト結果です。

4. 再度テストコードを修正します。今回は一度に大きな内容を出力するのではなく、バッファからクライアントに出力しきれない内容を意図的に操作します。クライアントに事前に出力します。

テストコード:

for ($i=0; $i < 10; $i++) { 
    fib(25);    setLog(date(&#39;H:i:s&#39;));    echo "hello " . date(&#39;H:i:s&#39;) . "<br>";
    ob_flush();
    flush();
}
//这里省略了fib和setLog函数

概要:

    原則として、クライアントがアクティブに切断すると、PHP スクリプトは実行を停止します
  • ただし、前提として、PHP はクライアントがどのように切断されるかを知っており、PHP が切断した場合にのみ実行されます。コンテンツをクライアントに出力します (PHP バッファーや Web サーバー バッファーではありません)。PHP はクライアント接続が中断されたことを認識し、実行を停止します
  • PHP がクライアントにコンテンツを出力するには 2 つの方法があります。 1 つ目は、コンテンツをバッファに入れてクライアントに自動的に送信することです。2 つ目は、バッファのコンテンツをクライアントにアクティブにフラッシュするフラッシュ関数である
  • php スクリプトの実行も制限されます。内部スクリプトタイマー。php .ini で実行するか、ホスト Apache 構成ファイルで設定するか、スクリプト内の set_time_limt 関数で設定できます。
  • クライアントがアクティブに切断しても、php スクリプトの実行が停止しない場合、
  • PHP スクリプトがignore_user_abort(true) を設定すると、クライアント接続が切断され、PHP がコンテンツをクライアントに出力し、クライアント接続が切断されたことを認識している場合でも、スクリプトの実行は行われます。停止しない;
  • php の内部では、維持された接続ステータスは関数 connection_status の戻り値を通じて確認できます。 0: 中断 (切断); 変更されたステータスの検出も必要です。 PHP スクリプトは、コンテンツが認識される前にクライアントに出力します。それ以外の場合は、常に 0 になります。
  • クライアントの接続が切断されたかどうか (connection_aborted) を検出できる関数もあります。0 は正常です。 , 1 が切断されました。
  • 奇妙な問題は、クライアント接続が切断され、PHP スクリプトが 2 回出力されると、ステータスビットが 1 になることです。
  • 2 番目に、PHP サーバーが積極的に切断します

PHP を積極的に切断するには、 http 応答ヘッダーの content-length と connection の 2 つのフィールドの意味は次のとおりです:

    content-length クライアントが応答ヘッダーの content-length を受信すると、指定されたサイズを受信した後、対応する本文として使用されます。 、サーバーへの接続が切断されます;
  • 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



以上がhttpブラウザはアクティブに切断し、phpはアクティブに切断しますの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。