Calender
Sun Mon Tue Wed Thu Fri Sat
 123456
78910111213
14151617181920
21222324252627
28293031   
<< May 2017 >>
広告
SEARCH

SELECTED ENTRIES
RECENT COMMENTS
RECENT TRACKBACK
CATEGORIES
ARCHIVES
LINKS
PROFILE
OTHERS
SKYPE
PC: skype.jojo.jp
chat
iPad: iphone.jojo.jp
chat call
THANKS



本日:
昨日:
多言語
広告
 ▼▲ 作業日報 ▼△
    What's under the hood?
<< 桜、愛知県江南市役所前 | main | PHPのヒアドキュメント、$文字に注意 >>
ignore_user_abort(false)でPHPが処理を中断しない件
 ユーザ側の切断で処理を続行すべきかどうかを調整する「ignore_user_abort()」関数がありますが、バッファ処理を行っていないと処理は中断されません
 下のコードは15秒間カウントを出力しますが、途中でブラウザを閉じたり、MSXML2.ServerXMLHTTP等のオブジェクトから切断された場合にはabortされるものだと思っていました
 実際には、バッファ制御が明示的に行われていない場合、リクエスト側から切断されていても検知できず、バッファの内容が(自動的にでも)送信されるまでは処理は実行され続けることになります、重めの処理を実行させる場合は、サーバのリソースを無駄にしない為にも適時flush()が必要かなと思います
<?
header
('Content-type: text/plain;');
//↓ true...切断無視で動く、false...切断されて中断
ignore_user_abort(false);

file_put_contents('log.txt',ignore_user_abort()."¥n");
for ( 
$i=$i<15$i++){
    
//カウントを出力
    
echo($i);
    
//ログへ出力
    
file_put_contents('log.txt',"$i..".connection_aborted()."(".connection_status().")¥n",FILE_APPEND);
    
sleep(1);//1秒の待機
}
?>
↓が正解のコードです
<?
header
('Content-type: text/plain;');
//↓ true...切断無視で続行、false...切断されて中断
ignore_user_abort(false);

ob_start();//バッファを制御開始

file_put_contents('log.txt',ignore_user_abort()."¥n");
for ( 
$i=$i<15$i++){
    
//カウントを出力
    
echo($i);
    
ob_flush();
    
flush();
    
//ログへ出力
    
file_put_contents('log.txt',"$i..".connection_aborted()."(".connection_status().")¥n",FILE_APPEND);
    
sleep(1);//1秒の待機
}
?>

1)ignore_user_abort(false);時のlog.txtの内容(下コード)
0
0..0(0)
1..0(0)
2..0(0)
3..0(0)
4..0(0)
5..0(0)
6..0(0)
    ←ここでブラウザを閉じたのでスクリプトは中断した

2)ignore_user_abort(true);時のlog.txtの内容(下コード)

1
0..0(0)
1..0(0)
2..0(0)
3..0(0)
4..0(0)
5..0(0)
6..0(0)
7..0(0)
8..0(0)
9..1(1) <-ブラウザを閉じた
10..1(1) connection_abortedの状態は変化し継続
11..1(1)
12..1(1)
13..1(1)
14..1(1)

ignore_user_abort(false)でバッファ処理を行わない(上コード)
0
0..0(0)
1..0(0)
2..0(0)
3..0(0)
4..0(0)
5..0(0)
6..0(0)
7..0(0)//←ブラウザ閉じても、切断されても
8..0(0)  実際の通信は行われていないので
9..0(0)  相手が閉じているかどうかが分からず
10..0(0) 中断されない
11..0(0)
12..0(0)
13..0(0)
14..0(0)
 補足ですが、IEでは256バイト受信しないとレンダリングが始まらりませんので、今回の例ではflush()してもブラウザに数字が表示されるわけではありません、又echo("")やecho(null)ではflush()しても通信は行われず、connection_aborted()は変化しません(従って下のVBAでは7秒のReceiveTimeoutが発生します)

XMLHTTPオブジェクトの検証用(VBS):
Option Explicit

Dim strURL
Dim objHTTP

strURL = "http://127.0.0.1/hogehoge/test.php"

set objHTTP = CreateObject("MSXML2.ServerXMLHTTP")

objHTTP.setTimeouts 1000,1000,3000,7000 'タイムアウトは7秒

objHTTP.open "GET",strURL,false

objHTTP.send

if objHTTP.status = 200 then
WScript.echo objHTTP.responseText
else
WScript.echo "レスポンスコードが異常です:" & objHTTP.status
end if

set objHTTP = Nothing

ignore_user_abort()のマニュアルをみると「注意」のところに「flush()を参照」と書いてありましたたらーっ

最初違う趣旨(MSXML2.ServerXMLHTTP.setTimeouts()で処理中断しない)で書いていたのですが、検証しているうちに原因がここだと分かりました(^^;
因みにMSXML2.ServerXMLHTTP.setTimeouts()の第4パラメータのReceiveTimeoutは無通信状態が続く間隔(ms)の事で、リクエスト->レスポンス終了までではないようです
| - | 16:28 | comments(2) | trackbacks(0) |
トラックバックありがとうございます!
バッファ処理はノーチェックでした(汗)
| nishijima | 2008/04/05 8:42 PM |
情報ありがとうございます。助かりました!

8年も前の記事に救われるとは…成長していない証か(^_^;

しかも、マニュアルに書いてあったんですね(;´Д`)
| taka | 2016/08/26 4:12 PM |









http://blog.jojo.jp/trackback/867079