6

クライアントがブラウザーを閉じても (サーバーへの接続が閉じられると)、このダミー スクリプトがイベントを実行し続けるのはなぜですか?

while (真)
{
    スリープ ( 1 );
    file_put_contents( '/tmp/foo' , "私は生きています ".getmypid()."\n" , FILE_APPEND );
}

これによると、私には予想外です。また、この例はうまくいかないようです。

また、ゼロ以外のパラメーターを指定したset_time_limitは、単に何もしません。

いくつかの説明が欲しいです。

4

2 に答える 2

9

そのループでブラウザに出力を書き込もうとすると、接続が終了するとスクリプトが中止されることがわかります。この動作は、ignore_user_abortのドキュメントで示唆されています

PHP をコマンド ライン スクリプトとして実行し、スクリプトを終了せずにスクリプトの tty を終了すると、値が TRUE に設定されていない限り、次に何かを書き込もうとしたときにスクリプトが終了します。

私自身、いくつかの実験を試みたところ、ブラウザ出力を試みても、出力バッファがまだいっぱいになっていない限り、スクリプトは実行され続けることがわかりました。出力バッファリングをオフにすると、出力が試行されるとスクリプトは中止されます。これは理にかなっています。SAPI レイヤーは、出力を送信しようとしたときに、要求が終了したことに気付くはずです。

ここに例があります...

//ensure we're  not ignoring aborts..
ignore_user_abort(false);

//find out how big the output buffer is
$buffersize=max(1, ini_get('output_buffering'));


while (true)
{
    sleep( 1 );

    //ensure we fill the output buffer - if the user has aborted, then the script
    //will get aborted here
    echo str_repeat('*', $buffersize)."\n";

    file_put_contents( '/tmp/foo' , "I'm alive ".getmypid()."\n" , FILE_APPEND );
}

これは、アボートをトリガーするものを示しています。出力のない無限ループに陥りがちなスクリプトがある場合は、connection_aborted()を使用して、接続がまだ開いているかどうかをテストできます。

于 2011-07-14T19:27:13.510 に答える
1

set_time_limitPHPコードで費やされる時間のみを制限します。プログラムのほとんどの時間 (99.9% を超えると思います) は、システム コール、ファイルへのデータの書き込み、およびスリープに費やされます。

ignore_user_abortクライアントに(ローカルファイルではなく)何かを書き込んでいるときにのみ中止されます-クライアントがRSTパケットで明示的に接続を終了しない限り、TCPでは未使用の接続と終了した接続を区別する方法はありません。

于 2011-07-14T19:32:19.250 に答える