Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
251 views
in Technique[技术] by (71.8m points)

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

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.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...