I believe that many people have headaches about the curl_multi family of functions that are unclear in the PHP manual. They have few documents and the examples given are so simple that you cannot learn from them. I have also searched many web pages, but I have not found a complete application. example.
curl_multi_add_handle
curl_multi_close
curl_multi_getcontent
curl_multi_info_read
curl_multi_init
curl_multi_remove_handle
curl_multi_select
Generally speaking, when you think of using these functions, the purpose should obviously be to request multiple URLs at the same time, rather than requesting them one by one, otherwise it is not as good as yourself Loop to adjust curl_exec.
The steps are summarized as follows:
Step one: Call curl_multi_init
Step two: Call curl_multi_add_handle in a loop
It should be noted in this step that the second parameter of curl_multi_add_handle is given by Subhandle from curl_init.
Step 3: Continuously call curl_multi_exec
Step 4: Cyclically call curl_multi_getcontent to obtain the results as needed
Step 5: Call curl_multi_remove_handle, and call curl_close for each word handle
Step 6: Call curl_multi_close
Here is a simple example found online. The author calls it a dirty example (I will explain why it is dirty later):
/* 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);
The whole usage process is almost like this, but, This simple code has a fatal weakness, that is, the part of the do loop is an infinite loop during the entire url request, which can easily cause the CPU to occupy 100%.
Now let's improve it. Here we need to use a function curl_multi_select that has almost no documentation. Although C's curl library has instructions for select, the interface and usage in PHP are indeed different from those in C. .
Change the do paragraph above to the following:
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); } }
Because $active has to wait until all url data is received before it becomes false, so the return value of curl_multi_exec is used here to determine whether it is still If there is data, curl_multi_exec will be called continuously when there is data. If there is no data for the time being, it will enter the select phase. Once new data comes, it can be awakened to continue execution. The advantage here is that there is no unnecessary consumption of CPU.
In addition: There are some details that may sometimes be encountered:
Control the timeout of each request, do it through curl_setopt before curl_multi_add_handle:
curl_setopt($ch , CURLOPT_TIMEOUT, $timeout);
To determine whether it has timed out or other errors, use: 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();
The above is the detailed content of An explanation of the application of curl_multi related functions in PHP. For more information, please follow other related articles on the PHP Chinese website!