curl_multi_exec

(PHP 5)

curl_multi_execFührt die Unter-Verbindungen des cURL-Handles aus

Beschreibung

int curl_multi_exec ( resource $mh , int &$still_running )

Verarbeitet alle Handles; diese Methode kann unabhängig davon aufgerufen werden, ob eines der Handles Daten lesen oder schreiben muß.

Parameter-Liste

mh

Ein von curl_multi_init() zurückgegebenes cURL-Multihandle.

still_running

Eine Referenz auf ein Flag um festzustellen, ob auf einem oder mehreren Handles noch gearbeitet wird.

Rückgabewerte

Ein cURL-Code der in den cURL Vordefinierten Konstanten definiert ist.

Hinweis:

Es werden nur Fehler zurückgegeben, die den Handle-Stack betreffen. Auch wenn CURLM_OK zurückgegeben wird können auf einzelnen Handles Fehler aufgetreten sein.

Beispiele

Beispiel #1 curl_multi_exec()-Beispiel

In diesem Beispiel werden zwei cURL-Handles erstellt, einem Mehrfach-Handle hinzugefügt und anschließend parallel ausgeführt.

<?php
// zwei cURL Resourcen erstellen
$ch1 curl_init();
$ch2 curl_init();

// URL und weitere Optionen setzen
curl_setopt($ch1CURLOPT_URL"http://lxr.php.net/");
curl_setopt($ch1CURLOPT_HEADER0);
curl_setopt($ch2CURLOPT_URL"http://www.php.net/");
curl_setopt($ch2CURLOPT_HEADER0);

// Mehrfach-Handle erstellen
$mh curl_multi_init();

// die zuvor erstellten Handles hinzufügen
curl_multi_add_handle($mh,$ch1);
curl_multi_add_handle($mh,$ch2);

$active null;
// Handles ausführen
do {
    
$mrc curl_multi_exec($mh$active);
} while (
$mrc == CURLM_CALL_MULTI_PERFORM);

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

//close the handles
curl_multi_remove_handle($mh$ch1);
curl_multi_remove_handle($mh$ch2);
curl_multi_close($mh);

?>

Siehe auch

add a note add a note

User Contributed Notes 8 notes

up
9
Ren
8 months ago
Solve CPU 100% usage, a more simple and right way:

<?php

do {
   
curl_multi_exec($mh, $running);
   
curl_multi_select($mh);
} while (
$running > 0);

?>
up
1
viczbk.ru
6 years ago
http://curl.haxx.se/libcurl/c/libcurl-multi.html

"When you've added the handles you have for the moment (you can still add new ones at any time), you start the transfers by call curl_multi_perform(3).

curl_multi_perform(3) is asynchronous. It will only execute as little as possible and then return back control to your program. It is designed to never block. If it returns CURLM_CALL_MULTI_PERFORM you better call it again soon, as that is a signal that it still has local data to send or remote data to receive."

So it seems the loop in sample script should look this way:

<?php
$running
=null;
//execute the handles
do {
    while (
CURLM_CALL_MULTI_PERFORM === curl_multi_exec($mh, $running));
    if (!
$running) break;
    while ((
$res = curl_multi_select($mh)) === 0) {};
    if (
$res === false) {
        echo
"<h1>select error</h1>";
        break;
    }
} while (
true);
?>

This worked fine (PHP 5.2.5 @ FBSD 6.2) without running non-blocked loop and wasting CPU time.

However this seems to be the only use of curl_multi_select, coz there's no simple way to bind it with other PHP wrappers for select syscall.
up
0
pulksh at gmail dot com
1 month ago
This example not working on window 7 with php version 5.3.27.
up
-1
Jimmy Ruska
5 years ago
> replying to viczbk.ru

Just sharing my attempt at it.

> while (($res = curl_multi_select($mh)) === 0) {};
This worked on my windows computer (php 5.2.5) but when I ran the curl program in my new centOS server (php 5.1.6) the function never updates unless curl_multi_exec() is added to the loop, taking away the point of using it to save cycles. curl_multi_select() also allows you to set a timeout but it doesn't seem to help, then again, don't see why people wouldn't use it anyway.

Even when curl_multi_select($mh) does work there's no way to know which of the sockets updated in status or if they've received partial data, completely finished, or just timed out. It's not reliable if you want to remove / add data as soon as things finish. Try calling just example.com or some other website with very little data. curl_multi_select($mh) can send non 0 value a couple of thousand times before finishing. Lazily adding a usleep(25000) or some minimal amount can also help not waste cycles.
up
-1
robert dot reichel at boboton dot com
6 years ago
I was testing PHP code provided by dtorop933@gmail.com in curl_multi_exec section of PHP Manual.

The part of the code '$err = curl_error($conn[$i])' should return error message for each cURL session, but it does not.
The function curl_error() works well with the curl_exec(). Is there any other solution for getting session error message with curl_multi_exec() or there is a bug in cURL library.

The script was tested with Windows XP and PHP-5.2.4
up
-1
substr(&#34;iscampifriese&#34;,1,11) dot &#34; at beer dot com&#34;
6 years ago
If you are using mulit handles and you wish to re-execute any of them (if they timed out or something), then you need to remove the handles from the mulit-handle and then re-add them in order to get them to re-execute.  Otherwise cURL will just give you back the same results again without actually retrying.
up
-2
Daniel G Zylberberg
1 year ago
This function wait for the last page, can get a configuration array with curl options to made a post, or pass timeouts, etc.
Retun the same array but add "error", and "data".Error is the string destription if something fail, data is the response.

<?php
// author: Daniel G Zylberberg
// date 11 jul 2012
// $res: array with structure 0=>array("url"=>"blah"),1=>array("url"=>"some url")
// $options (optional): array with curl options (timeout, postfields, etc)
// return the same array that gets, and add "data" to the current row(html content)
// and "error", with the string description in the case that something fail.

function multiCurl($res,$options=""){

        if(
count($res)<=0) return False;

       
$handles = array();

        if(!
$options) // add default options
           
$options = array(
               
CURLOPT_HEADER=>0,
               
CURLOPT_RETURNTRANSFER=>1,
            );

       
// add curl options to each handle
       
foreach($res as $k=>$row){
           
$ch{$k} = curl_init();
           
$options[CURLOPT_URL] = $row['url'];
           
curl_setopt_array($ch{$k}, $options);
           
$handles[$k] = $ch{$k};
        }

       
$mh = curl_multi_init();

        foreach(
$handles as $k => $handle){
           
curl_multi_add_handle($mh,$handle);
           
//echo "<br>adding handle {$k}";
       
}

       
$running_handles = null;
       
//execute the handles
       
do {
           
$status_cme = curl_multi_exec($mh, $running_handles);
        } while (
$cme == CURLM_CALL_MULTI_PERFORM);

        while (
$running_handles && $status_cme == CURLM_OK) {
            if (
curl_multi_select($mh) != -1) {
                do {
                   
$status_cme = curl_multi_exec($mh, $running_handles);
                  
// echo "<br>''threads'' running = {$running_handles}";
               
} while ($status == CURLM_CALL_MULTI_PERFORM);
            }
        }

        foreach(
$res as $k=>$row){
           
$res[$k]['error'] = curl_error($handles[$k]);
            if(!empty(
$res[$k]['error']))
               
$res[$k]['data']  = '';
            else
               
$res[$k]['data']  = curl_multi_getcontent( $handles[$k] );  // get results

            // close current handler
           
curl_multi_remove_handle($mh, $handles[$k] );
        }
       
curl_multi_close($mh);
        return
$res; // return response
}

$res = array(
       
"11"=>array("url"=>"http://localhost/public_html/test/sleep.php?t=1"),
       
"13"=>array("url"=>"http://localhost/public_html/test/sleep.php?t=3"),
       
"25"=>array("url"=>"this doesn't exist"),

);
print_r( multiCurl($res));
?>

---------- sleep.php -------------------------------------
<?php
sleep
($_GET['t']);
echo
"sleep for {$_GET['t']} seconds and show this.";
?>
up
-2
emmet at trovit dot com
1 year ago
Here's something that had me pulling my hair out for quite a while. I was trying to download multiple files and save each one in a file. If you want to read the file again in the same script that has downloaded the url, always make sure to close the original filehandle that you opened for the connection BEFORE trying to read from the file again, even if you open a new filehandle to do so. If you don't do this, a file_get_contents() or fread() will cut your file and only return a limited size of it, 40960 characters in my case, without any other explanation or error. The file will exist (and be complete) on your disk, PHP just wont show it.

I (perhaps mistakenly) thought this was a bug so I created a bug report, see it for examples of the code I used to recreate this misterious behavior:
https://bugs.php.net/bug.php?id=62409
To Top