ホームページ  >  記事  >  バックエンド開発  >  PHP でのcurl_multi関連​​関数のアプリケーションの説明

PHP でのcurl_multi関連​​関数のアプリケーションの説明

巴扎黑
巴扎黑オリジナル
2017-05-25 17:45:341326ブラウズ

多くの人が、PHP マニュアルでは不明瞭な、curl_multi 関数ファミリーについて頭を悩ませていると思います。それらのドキュメントはほとんどなく、示されている例は非常に単純なので、そこから学ぶことはできません。しかし、私も多くの Web ページを検索しました。完全なアプリケーション例を見たことがありません。

curl_multi_add_handle

curl_multi_close

curl_multi_exec

curl_multi_getcontent

curl_multi_info_read

curl_multi_init

curl_multi_remove_handle

curl_multi_select

一般的に、これらの関数の使用を考えるとき、その目的は明らかに、同時にそれらを 1 つずつリクエストするのではなく、ループ内でcurl_execを自分で調整することをお勧めします。

ステップは次のように要約されます:

ステップ 1:curl_multi_init を呼び出す
ステップ 2:ループ内でcurl_multi_add_handleを呼び出す
このステップでは、curl_multi_add_handle の 2 番目のパラメーターがcurl_init のサブハンドルであることに注意してください。
ステップ 3: 引き続きcurl_multi_execを呼び出します
ステップ 4: 必要に応じてループ内でcurl_multi_getcontentを呼び出し、結果を取得します
ステップ 5:curl_multi_remove_handleを呼び出し、単語ハンドルごとにcurl_closeを呼び出します
ステップ6:curl_multi_closeを呼び出します

オンライン検索はこちらです単純な例で、著者はこれを汚い例と呼んでいます (なぜ汚いのかは後ほど説明します):

/*
Here's a quick and dirty example for curl-multi from PHP, tested on PHP 5.0.0RC1 CLI / FreeBSD 5.2.1
*/
$connomains = array(
"http://www.cnn.com/",
"http://www.canada.com/",
"http://www.yahoo.com/"
);
$mh = curl_multi_init();
foreach ($connomains as $i => $url) {
     $conn[$i]=curl_init($url);
      curl_setopt($conn[$i],CURLOPT_RETURNTRANSFER,1);
      curl_multi_add_handle ($mh,$conn[$i]);
}
do { $n=curl_multi_exec($mh,$active); } while ($active);
foreach ($connomains as $i => $url) {
      $res[$i]=curl_multi_getcontent($conn[$i]);
      curl_close($conn[$i]);
}
print_r($res);

使用プロセス全体はほぼ次のようになりますが、この単純なコードには致命的な弱点があります。それは do ループのセクションです。これは URL リクエスト全体で無限ループとなり、CPU が 100% を占有する可能性があります。

ここで、curl_multi_select 関数を使用する必要がありますが、この関数にはほとんどドキュメントがありませんが、PHP のインターフェイスと使用法は C のものとは異なります。

上記の do セクションを次のように変更します。

 do {
                        $mrc = curl_multi_exec($mh,$active);
                } while ($mrc == CURLM_CALL_MULTI_PERFORM);
                while ($active and $mrc == CURLM_OK) {
                        if (curl_multi_select($mh) != -1) {
                                do {
                                        $mrc = curl_multi_exec($mh, $active);
                                } while ($mrc == CURLM_CALL_MULTI_PERFORM);
                        }
                }

$active は、URL データがすべて受信されるまで false になるまで待機する必要があるため、ここでは、curl_multi_exec の戻り値を使用して、データが存在するかどうかを判断します。データが存在しない場合は、curl_multi_exec を呼び出し続けるだけです。新しいデータが到着すると、起動して実行を続行できます。この場合の利点は、CPU を不必要に消費しないことです。

さらに: 時々発生する可能性のある詳細がいくつかあります:

各リクエストのタイムアウトを制御し、curl_multi_add_handle の前にcurl_setopt を通して実行します:
curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);

判断タイムアウトまたはその他のエラーの場合は、curl_multi_getcontent の前に、curl_error($conn[$i])

class MultiCurl{
private $mch;
private $timeout;
private $urls;
private $chs;
private $errchs;
private $content;
public function __construct($urls, $timeout=300){
 $this->mch = curl_multi_init();
 $this->timeout =  $timeout;
 $this->urls = $urls;
 $this->chs = array();
 $this->errchs = array();
 $this->content = array();
}
public function ctlFlow(){
 $this->createhandle();
 $this->execurl();
 $this->chs = array();
 $this->errchs = array();
 echo "<pre class="brush:php;toolbar:false">";
 print_r($this->content);
 echo "
"; return $this->content; } private function createhandle(){ if(!empty($this->urls)){ foreach($this->urls as $k => $url){ $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_TIMEOUT, $this->timeout); curl_multi_add_handle($this->mch, $ch); $this->chs[$k] = $ch; } } } private function execurl(){ do { $mrc = curl_multi_exec($this->mch,$active); } while ($mrc == CURLM_CALL_MULTI_PERFORM); while ($active && $mrc == CURLM_OK) { if (curl_multi_select($this->mch) != -1) { usleep(300); do { $mrc = curl_multi_exec($this->mch, $active); } while ($mrc == CURLM_CALL_MULTI_PERFORM); } } foreach($this->chs as $k => $c){ if (curl_error($c) == '') { $temp = curl_multi_getcontent($c); $count = 0; while(!$temp){ if($count > 3) break; usleep(100); $temp = curl_multi_getcontent($c); $count++; } $this->content[$k] = $temp; unset($this->chs[$k]); curl_multi_remove_handle($this->mch, $c); curl_close($c); } else { $this->errchs[$k] = $this->urls[$k]; } } } } $urlArr = array('baidu'=>'www.baidu.com', 'google'=>'www.google.com.hk', 'sogou'=>'www.sogou.com'); $mucurl = new MultiCurl($urlArr); $mucurl->ctlFlow(); を使用します。

以上がPHP でのcurl_multi関連​​関数のアプリケーションの説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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