PHP curl_multi_getcontent返回null

时间:2013-09-13 23:26:21

标签: php curl curl-multi

我一直在关注如何使用curl_multi的本教程。 http://arguments.callee.info/2010/02/21/multiple-curl-requests-with-php/

我无法说出我做错了什么,但curl_multi_getcontent正在返回null。假设返回JSON。我知道这不是mysql调用,因为我使用了while循环和标准curl_exec,但页面加载时间太长。 (我已经更改了一些setopt详细信息以确保安全性)

相关的PHP代码段。我最后关闭了while循环。

$i = 0;
$ch = array();
$mh = curl_multi_init();
while($row = $result->fetch_object()){
   $ch[$i] = curl_init();
   curl_setopt($ch[$i], CURLOPT_CAINFO, 'cacert.pem');
   curl_setopt($ch[$i], CURLOPT_USERPWD, "$username:$password");
   curl_setopt($ch[$i], CURLOPT_RETURNTRANSFER, true); 
   curl_setopt($ch[$i], CURLOPT_URL, 'https://mysite.com/search/'.$row->username.'/');
   curl_multi_add_handle($mh, $ch[$i]);
   $i++;
}
$running = 0;
do {
    curl_multi_exec($mh, $running);
} while ($running > 0);
$result->data_seek(0);
$i = 0;
while ($row = $result->fetch_object()) {
    $data = curl_multi_getcontent($ch[$i]);
    $json_data = json_decode($data);
    var_dump($json_data);

修改

以下是当前有效的代码,但导致页面加载速度太慢

$ch = curl_init();
curl_setopt($ch, CURLOPT_CAINFO, 'cacert.pem');
curl_setopt($ch, CURLOPT_USERPWD, "$username:$password");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 
while($row = $result->fetch_object()){
   curl_setopt($ch, CURLOPT_URL, 'https://mysite.com/search/'.$row->username.'/');
   $data = curl_exec($ch);
   $json_data = json_decode($data);
   var_dump($json_data);
}

5 个答案:

答案 0 :(得分:2)

我想知道:

$i = 0;
while ($row = $result->fetch_object()) {
    $data = curl_multi_getcontent($ch[$i]);
    $json_data = json_decode($data);
    var_dump($json_data);

你忘了增加$ i吗?如果是这样,你已经抓住$ ch [0]的内容,然后再次调用curl_multi_getcontent。

另外,我写了一篇关于concurrent requests with PHP's cURL extension的博客文章,它包含了curl多请求的一般功能。您可以通过以下方式调用此函数:

$responses = multi([
    $requests = [
        ['url' => 'https://mysite.com/search/username1/'],
        ['url' => 'https://mysite.com/search/username2/'],
        ['url' => 'https://mysite.com/search/username3/']
    ]
    $opts = [
        CURLOPT_CAINFO => 'cacert.pem',
        CURLOPT_USERPWD => "username:password"
    ]
]);

然后,循环遍历响应数组:

foreach ($responses as $response) {
    if ($response['error'] {
        // handle error
        continue;
    }
    // check for empty response
    if ($response['data'] === null) {
        // examine $response['info']
        continue;
    }
    // handle data
    $data = json_decode($response['data']);
    // do something
}

使用此功能,您可以使用以下调用进行访问https站点的简单测试:

multi(
    $requests = [
        'google' => ['url' => 'https://www.google.com'],
        'linkedin' => ['url'=> 'https://www.linkedin.com/']
    ],
    $opts = [
        CURLOPT_CAINFO => '/path/to/your/cacert.pem',
        CURLOPT_SSL_VERIFYPEER => true
    ]
);

答案 1 :(得分:1)

我看到你的执行循环与PHP documentation中提出的建议循环不同:

do {
  $mrc = curl_multi_exec($mh, $active);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);

请注意,在while中比较函数return,而不是第二个参数。

修改: 感谢Adam的评论,我测试了两种语法,看到它们是相同的和异步的。 以下是将内容转换为变量的异步多请求的工作示例:

<?php
$ch = array();
$mh = curl_multi_init();
$total = 100;

echo 'Start: ' . microtime(true) . "\n";

for ($i = 0; $i < $total; $i++) {
    $ch[$i] = curl_init();
    curl_setopt($ch[$i], CURLOPT_URL, 'http://localhost/sleep.php?t=' . $i);
    curl_setopt($ch[$i], CURLOPT_HEADER, 0);
    curl_setopt($ch[$i], CURLOPT_RETURNTRANSFER, true);

    curl_multi_add_handle($mh, $ch[$i]);
}

$active = null;
do {
    $mrc = curl_multi_exec($mh, $active);
    usleep(100); // Maybe needed to limit CPU load (See P.S.)
} while ($active);

foreach ($ch AS $i => $c) {
    $r = curl_multi_getcontent($c);
    var_dump($r);
    curl_multi_remove_handle($mh, $c);
}

curl_multi_close($mh);

echo 'End: ' . microtime(true) . "\n";

测试文件sleep.php:

<?php
$start = microtime(true);

sleep( rand(3, 5) );

$end = microtime(true);

echo $_GET['t'], ': ', $start, ' - ', $end, ' - ', ($end - $start);
echo "\n";

P.S。在循环中使用usleep的初步想法是暂停一点,从而减少cUrl等待响应时的操作次数。而在一开始它似乎以这种方式工作。但是top的最后一次测试显示CPU负载的差异很小(17%与usleep相比,而没有它的则为20%)。所以,我不知道是否使用它。也许真实服务器上的测试会显示另一个结果。

编辑2 :我测试了我的代码,向密码保护的HTTPS页面发出请求(CURLOPT_CAINFOCURLOPT_USERPWD等于问题中的那些页面)。它按预期工作。您的PHP或cURL版本可能存在错误。我的版本是&#34; PHP版本5.3.10-1ubuntu3.8&#34;和7.22.0。他们没有问题。

答案 2 :(得分:0)

使用$running = null;代替$running = 0;

根据链接:

  1. multiple-curl-requests-with-php

  2. http://www.php.net/manual/en/function.curl-multi-exec.php

  3. 在这两种情况下,变量都被定义为NULL,这是因为

    curl_multi_exec ( resource $mh , int &$still_running )
    

    第二个参数是对变量的引用。

    此外,您可能会发现这有用:php single curl works but multi curl doesn't work

答案 3 :(得分:0)

您是否将CURLOPT_SSL_VERIFYPEER设置为true?

答案 4 :(得分:-1)

curl_multi_exec执行多线程HTTP请求,请求可能不是按照您已将它们添加到多处理程序$mh的顺序完成的。要获得已完成请求的响应,您应该使用curl_multi_info_read函数。您可以在php.net http://php.net/manual/ru/function.curl-multi-info-read.php

上阅读更多相关信息