Web サーバーはスクリプトを実行しますが、これは数ミリ秒で完了する場合もあれば、数分以内に完了しない場合もあります。プログラムの実行が遅い場合、ユーザーはそれ以上待つ忍耐力がなくなり、ブラウザを閉じる可能性があります。
場合によっては、これらの時間のかかるスクリプトの実行結果を気にしないこともありますが、次のステップに進む前に、スクリプトの実行が完了して戻るまで待つ必要があります。
それでは、これらの時間のかかるスクリプトの呼び出しを単純にトリガーして次のステップに進み、これらの時間のかかるスクリプトをサーバー側でゆっくり実行できるようにする方法はあるのでしょうか?
次に、fskoopen を使用してこの関数を実装します。
PHP は、fsockopen というソケット プログラミング をサポートしています。以前 CMS に取り組んでいたとき、SMTP 送信にも使用しました。
fskoopen は、リモート ホスト接続へのハンドルを返します。 fopen によって返されたハンドルを使用するのと同じように、彼女に対して fwrite、read fgets、fread などの操作を実行できます。
非同期 PHP の主な望ましい効果は、PHP スクリプトをトリガーしてすぐに戻り、サーバー側でゆっくりと実行されるようにすることです。この問題については、以前にも記事を書きました。
次に、fsockopen を使用してローカル サーバーに接続し、スクリプトの実行をトリガーし、スクリプトの実行が完了するのを待たずにすぐに戻ることができます。
function triggerRequest($url, $post_data = array(), $cookie = array())…{ $method = "GET"; //可以通过POST或者GET传递一些参数给要触发的脚本 $url_array = parse_url($url); //获取URL信息,以便平凑HTTP HEADER $port = isset($url_array['port'])? $url_array['port'] : 80; $fp = fsockopen($url_array['host'], $port, $errno, $errstr, 30); if (!$fp) …{ return FALSE; } $getPath = $url_array['path'] ."?". $url_array['query']; if(!empty($post_data))…{ $method = "POST"; } $header = $method . " " . $getPath; $header .= " HTTP/1.1\r\n"; $header .= "Host: ". $url_array['host'] . "\r\n "; //HTTP 1.1 Host域不能省略 /**//*以下头信息域可以省略 $header .= "User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.13) Gecko/20080311 Firefox/2.0.0.13 \r\n"; $header .= "Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,q=0.5 \r\n"; $header .= "Accept-Language: en-us,en;q=0.5 "; $header .= "Accept-Encoding: gzip,deflate\r\n"; */ $header .= "Connection:Close\r\n"; if(!empty($cookie))…{ $_cookie = strval(NULL); foreach($cookie as $k => $v)…{ $_cookie .= $k."=".$v."; "; } $cookie_str = "Cookie: " . base64_encode($_cookie) ." \r\n";//传递Cookie $header .= $cookie_str; } if(!empty($post_data))…{ $_post = strval(NULL); foreach($post_data as $k => $v)…{ $_post .= $k."=".$v."&"; } $post_str = "Content-Type: application/x-www-form-urlencoded\r\n";//POST数据 $post_str .= "Content-Length: ". strlen($_post) ." \r\n";//POST数据的长度 $post_str .= $_post."\r\n\r\n "; //传递POST数据 $header .= $post_str; } fwrite($fp, $header); //echo fread($fp, 1024); //我们不关心服务器返回 fclose($fp); return true; }
これで、この 関数 を通じて PHP スクリプトの実行をトリガーでき、関数は戻ります。 その後、次のステップに進むことができます。
もう 1 つの問題は、クライアントが切断されたときです。つまり、triggerRequest がリクエストを送信した後、接続はすぐに閉じられるため、サーバー上で実行中のスクリプトが終了する可能性があります。
PHP 内部では、システムは接続 state を維持します。これには 3 つの状態が考えられます:
* 0 – NORMAL (正常)
* 1 – ABORTED (異常終了)
* 2 – TIMEOUT (タイムアウト)
PHP スクリプトが NORMAL 状態で正常に実行されている場合、接続は有効です。クライアントが切断されると、ABORTED ステータス フラグがオンになります。リモート クライアント接続の中断は、通常、ユーザーが STOP ボタンをクリックすることによって発生します。接続時間が PHP の制限時間 (set_time_limit() 関数を参照) を超えると、TIMEOUT 状態のフラグがオンになります。
クライアントが切断されたときにスクリプトを終了する必要があるかどうかを決定できます。リモート ブラウザがスクリプトの出力を受け入れない場合でも、スクリプトを完全に実行すると便利な場合があります。デフォルトでは、リモート クライアント接続が失われたときにスクリプトが終了します。この処理は、php.ini のignore_user_abort によって、または Apache .conf 設定の対応する "php_valueignore_user_abort" およびignore_user_abort() 関数によって制御できます。 PHP がユーザーの中断を無視するように指示されていない場合、 register_shutdown_function() を経由しない限り、スクリプトは中断されます。 シャットダウントリガー機能が設定されます。このクローズ トリガー関数により、リモート ユーザーが STOP ボタンをクリックし、スクリプトがデータを再度出力しようとすると、PHP は接続が中断されたことを検出し、クローズ トリガー関数を呼び出します。
スクリプトは、組み込みのスクリプト タイマーによって中断される場合もあります。デフォルトのタイムアウト制限は 30 秒です。この値は、php.ini で max_execution_time を設定するか、Apache .conf 設定の対応する「php_value max_execution_time」パラメータまたは set_time_limit() 関数を設定することで変更できます。カウンタがタイムアウトすると、上記の接続中断状況と同様にスクリプトが終了し、事前に登録されたシャットダウン トリガー関数もこの時点で実行されます。シャットダウン トリガー関数では、connection_status() 関数を呼び出すことで、タイムアウトによってシャットダウン トリガー関数が呼び出されたかどうかを確認できます。タイムアウトによりシャットダウントリガー関数が呼び出された場合、関数は戻り値を返します。 2.
注意すべき点の 1 つは、ABORTED 状態と TIMEOUT 状態が同時に有効になる可能性があるということです。これは、PHP にユーザー終了アクションを無視するように指示する場合に可能です。 PHP はユーザーが切断されたことを認識しますが、スクリプトはまだ実行中です。実行時間制限に達すると、スクリプトは終了し、設定されたシャットダウン トリガー関数も実行されます。この時点で、関数 connection_status() が 3 を返すことがわかります。
所以还在要触发的脚本中指明:
ignore_user_abort(TRUE); //如果客户端断开连接,不会引起脚本 abort.set_time_limit(0);//取消脚本执行延时上限
或者,也可以使用:
register_shutdown_function(callback fuction[, parameters]);//注册脚本退出时执行的函数
以上がfscok を使用して PHP への非同期呼び出しを実装する方法のコード例の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。