2012-03-07 14 views
1

私はclient.phpとserver.phpの2つのファイルを持っています。 クライアントファイルは、HTTP要求をサーバーファイルに送信します。サーバーファイルは要求を処理するのが非常に遅いので、クライアントに「OK」と答えてもらい、結果は電子メールで送信されます。サーバーから直接HTTPリクエストを中断する

しかし、私は適切なヘッダーでサーバーがHTTP要求を閉じて、そのジョブを続行させることを知らない。 1秒のタイムアウトを指定すると、要求がサーバーによって受け入れられるかどうかを知ることができません。

PHPでも可能ですか?どのようにするか知っていますか ?

client.php:

<?php 

$resource = curl_init(); 
curl_setopt($resource, CURLOPT_URL, 'http://localhost/server.php'); 
curl_setopt($resource, CURLOPT_RETURNTRANSFER, true); 
curl_setopt($resource, CURLOPT_TIMEOUT, 30); 
curl_exec($resource); 

server.phpという

<?php 

header('200 OK'); 
echo 'OK the request is correct, the result will be sent by email'; 

// How to write the method below? 
send_result_to_client(); 

// Simulates a slow process 
sleep(60); 

[OK]を、私は解決策を見つけました。関数send_result_to_clientで は、ように見えるはずです:

function send_result_to_client() 
{ 
    $myString = '...'; 
    $size = strlen($myString); 
    header("Content-Length: $size"); 
    header('Connection: close'); 
    flush(); 
} 

答えて

0

すみませんが、Connection:closeflush()を送信するソリューションではありません - ない移植性のサーバーやブラウザ間。 の場合はと表示される可能性があります。これは、単純なテストを実行するときに機能するように見えるためです。あなたは

send_result_to_client(); 
sleep(60); // simulate a job... 
mail(...); // ...ENDING with a mail message 

でそれを試してみて、その後、何もしない、または悪化した場合は、すべてのユーザーが何をするかやる - あなたは発見するでしょう - とすぐに、彼は「あなたは電子メールで通知されます」見てウィンドウを閉じますほとんどのプラットフォームでは、電子メールは送信されず、ジョブは決して完了しません。 Connection:closeContent-Lengthバイトが受信されている場合

curl

は終了することがありますが、

HTTP/1.1 defines the "close" connection option for **the sender** to signal that the connection will be closed after completion of the response. 

しかし、RFC 2616からサーバがない、本当に、接続を閉じていません。ジョブが処理される前に、die()またはexit()が必要になります。

ブラウザが実際に接続を閉じるまで、スクリプトは実行を継続します。その時点で(は通常)、処理が中止されます。たぶん、いくつかのプラットフォームではそうではありませんが、それを期待しません。

あなたは、他のハックで状況を改善しようとする場合があります。

set_time_limit(VERY_LONG_TIME); 
    ignore_user_abort(); 

が、それは、確かに、ハックです。

本当にポータブルなソリューションはありません。通常、Manatokが提案するように、ジョブは別の場所でキューに入れられ、キューは別のスレッドによって非同期に処理されます。おそらくこれが最良の解決策です。

他の可能性としては、atdとatコマンド(またはWindowsの同等機能)を使用してジョブをキューイングすることで、同じことを行う多分簡単な方法があります。あなたはatdによって実行される新しいPHPスクリプトをパイプでshell_execと「ジョブ制御」を作成することができます

shell_exec("echo 'php -q /path/to/script.php \"param1\" \"param2\" | at now"); 

(またはより効率的に、popenで「at now」を実行し、そのstdinに実行するコマンドを書きます) 。

例えば参照:

https://github.com/treffynnon/PHP-at-Job-Queue-Wrapper

ます。またpopenまたはshell_execを通じて、同時仕事を起動しようとすることができますが、サーバプロセスからそれを切り離す必要がある、またはあなたがシステムを見つけることができますジョブの実行可能ファイルのコピー(Windowsの場合はCMD.EXE)に悩まされていました。

参照:

Asynchronous shell exec in PHP

1

私は、これはあなたが(これが可能であることを確認しない)を求め、正確ものではありません知っているが、私は別のスレッドによって処理されるキューを持っているでしょう。要求はサーバーに送られ、キューに詳細が追加され(db内にある可能性があります)、クライアントに応答します。その後、キューを実行し、後でキューを処理することができます。

+0

[OK]を私は解決策を見つけました。私は元の投稿を編集しました。 –

+0

ああ、それは意味がある、素敵なものです。 – Manatok

+0

あなたが言ったのと同じことが可能です。 atd(またはスケジューラ、またはその周りのさまざまなポートとラッパーのいずれか)を使用してください。 crontabから実行している別のPHPスクリプト。 – LSerni

関連する問題