Maison  >  Article  >  développement back-end  >  Une explication de l'application des fonctions liées à curl_multi en PHP

Une explication de l'application des fonctions liées à curl_multi en PHP

巴扎黑
巴扎黑original
2017-05-25 17:45:341338parcourir

Je crois que beaucoup de gens ont des maux de tête à propos de la famille de fonctions curl_multi qui ne sont pas claires dans le manuel PHP. Ils ont peu de documents et les exemples donnés sont si simples que vous ne pouvez pas en tirer des leçons. mais je n'ai pas trouvé d'exemple d'application complet.

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

De manière générale, lorsque l'on pense utiliser ces fonctions, le but doit évidemment être de demander plusieurs URL en même temps, plutôt que de les demander une par un, sinon ce n'est pas aussi bon que vous-même Boucle pour ajuster curl_exec.

Les étapes sont résumées comme suit :

Étape 1 : Appeler curl_multi_init
Étape 2 : Appeler curl_multi_add_handle dans une boucle
Il est à noter dans cette étape que le deuxième paramètre de curl_multi_add_handle est donné par Subhandle de curl_init.
Étape 3 : Continuez à appeler curl_multi_exec
Étape 4 : Appelez curl_multi_getcontent en boucle pour obtenir les résultats nécessaires
Étape 5 : Appelez curl_multi_remove_handle et appelez curl_close pour chaque handle de mot
Étape 6 : Appelez curl_multi_close

Voici un exemple simple trouvé en ligne. L'auteur le qualifie d'exemple sale (j'expliquerai pourquoi il est sale plus tard) :

/*
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);

L'ensemble du processus d'utilisation est presque comme ça. Cependant, ce code simple a une faiblesse fatale, c'est-à-dire que la section de la boucle do est une boucle infinie pendant toute la requête d'URL, ce qui peut facilement amener le CPU à occuper 100 %.

Améliorons-le maintenant. Ici, nous devons utiliser une fonction curl_multi_select qui n'a presque aucune documentation. Bien que la bibliothèque curl de C ait des instructions pour la sélection, l'interface et l'utilisation en PHP sont en effet différentes de celles en C. .

Modifiez la section do ci-dessus comme suit :

 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);
                        }
                }

Parce que $active doit attendre que toutes les données d'URL soient reçues avant qu'elles ne deviennent fausses, le jugement de valeur de retour de curl_multi_exec est donc utilisé ici S'il y a encore des données, lorsqu'il y a des données, curl_multi_exec sera appelé en continu. S'il n'y a pas de données pour le moment, il entrera dans la phase de sélection. Une fois les nouvelles données arrivées, il pourra être réveillé pour continuer l'exécution. L’avantage ici est qu’il n’y a pas de consommation inutile de CPU.

De plus : Il y a quelques détails que vous pouvez rencontrer parfois :

Contrôlez le délai d'attente de chaque requête, faites-le via curl_setopt avant curl_multi_add_handle :
curl_setopt($ch , CURLOPT_TIMEOUT, $ timeout);

Pour déterminer s'il a expiré ou s'il y a d'autres erreurs, utilisez : 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(); avant curl_multi_getcontent

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn