Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

php single curl works but multi curl doesn't work?

Tags:

php

curl

libcurl

So I was using ampps and then switched to z-wamp thinking it would solve the issue, but it didn't.

I have separate "sites" in my localhost (localhost/site1 & localhost/site2) that I'm trying to send multi curl requests to, but for some odd reason, it's not doing anything! It only works when I do one single curl to one site. This works:

$ch = curl_init('http://localhost/site1/');
curl_setopt_array($ch, array(
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HEADER => false,
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => array('data' => $data)
));
$res = curl_exec($ch);
//yay!

In the other hand, this doesn't work:

...
//add a bunch of curl sessions
//to $this->sessions
...
$window = 15;
if (count($this->sessions) < $window)
    $window = count($this->sessions);

$mh = curl_multi_init();

$site_map = array();

for ($i = 0; $i < $window; ++$i) {
    curl_multi_add_handle($mh, $this->sessions[$i]);
    $site_map[(string) $this->sessions[$i]] = $i;
}

$data_results = array();
$running = null;

do {
    $execrun = curl_multi_exec($mh, $running);
} while ($execrun === CURLM_CALL_MULTI_PERFORM);

while ($running && $execrun === CURLM_OK) {

    //the loop just keeps going forever from here

    if (curl_multi_select($mh) !== -1) {
        do {
            $execrun = curl_multi_exec($mh, $running);
        } while ($execrun === CURLM_CALL_MULTI_PERFORM);
    }

    if ($execrun !== CURLM_OK)
        break;

    //to here and never enters the loop below

    while ($done = curl_multi_info_read($mh)) {

        $output = curl_multi_getcontent($done['handle']);

        if ($output)
            $data_results[$site_map[(string) $done['handle']]] = $output;
        else
            $data_results[$site_map[(string) $done['handle']]] = null;

        if (isset($this->sessions[$i]) && $i < count($this->sessions)) {
            curl_multi_add_handle($mh, $this->sessions[$i]);
            $site_map[(string) $this->sessions[$i]] = $i;
            ++$i;
        }

        unset($site_map[(string) $done['handle']]);
        curl_multi_remove_handle($mh, $done['handle']);
        curl_close($done['handle']);
    }
}
curl_multi_close($mh);
return $data_results;

So in the multi curl code above, it starts going, adds the handles to the $mh, and once it executes, it will keep looping and never go into the $done = curl_multi_info_read($mh) while loop. Meanwhile it is still running fine and also $running equals 2 the whole time. Also, curl_multi_info_read will return false. So it just keeps looping forever.

My curl extension is enabled (obviously, if single curl works) and here are the details of it from PHP Info:

cURL support    enabled
cURL Information    7.24.0
Age 3
Features
AsynchDNS   Yes
Debug   No
GSS-Negotiate   No
IDN No
IPv6    Yes
Largefile   Yes
NTLM    Yes
SPNEGO  No
SSL Yes
SSPI    No
krb4    No
libz    Yes
CharConv    No
Protocols   dict, file, ftp, ftps, gopher, http, https, imap, imaps, ldap, pop3, pop3s, rtsp, scp, sftp, smtp, smtps, telnet, tftp
Host    i386-pc-win32
SSL Version OpenSSL/1.0.0g
ZLib Version    1.2.5
libSSH Version  libssh2/1.3.0

What in the world is going on with this thing? Could it be something with my PHP config? Apache config? Once again, I'm using z-wamp.

PHP version 5.3.10 Apache version 2.4.1 Win 7 64-bit Added the PHP dir to PATH

Edit It turns out that it must be some kind of Apache/PHP config type issue that I can't spot at all because I did away with z-wamp and installed wampserver and it worked this time.

like image 793
rclai Avatar asked Mar 23 '12 14:03

rclai


1 Answers

I just answered another question that I found about multiple curl calls.

This is all I did to run the requests.

do {
    $status = curl_multi_exec($mh, $running);
} while ($status === CURLM_CALL_MULTI_PERFORM || $running);

Then I fetched the info I needed by looping over my array of curl handlers.

$returned = array();
foreach ($requests as $identifier => $request) {
    $returned[$identifier] = curl_multi_getcontent($request);
    curl_multi_remove_handle($mh, $request);
    curl_close($request);
}

The above approach worked for me, however it seems like you want to add only a certain amount of sessions to the curl multi-handler. We could probably change the do-while loop above to the following:

do {
    $status = curl_multi_exec($mh, $running);
    if ($running < $window) {
        for ($x = 0; $x < $window - $running; $x++) {
            $index = count($site_map) + $x -1;
            curl_multi_add_handle($mh, $this->sessions[$index]);
            $site_map[(string) $this->sessions[$index]] = $index;
        }
    }
} while ($status === CURLM_CALL_MULTI_PERFORM || $running);

After that we could modify the data fetch and replace your whole while ($running && $execrun === CURLM_OK){} section with the following since it will only run once all your curl calls have been processed:

$returned = array();
foreach ($this->sessions as $identifier => $request) {
    $returned[$identifier] = curl_multi_getcontent($request);
    curl_multi_remove_handle($mh, $request);
    curl_close($request);
}
like image 112
Crashspeeder Avatar answered Oct 23 '22 04:10

Crashspeeder