与CURL Multi PHP不一致

前端之家收集整理的这篇文章主要介绍了与CURL Multi PHP不一致前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
当我对10个URL进行检查时,如果我能够与主机服务器建立连接,则句柄将返回成功消息(CURLE_OK)

当服务器拒绝连接时处理每个句柄时,句柄将包含错误消息.

问题

我假设当我们得到一个坏句柄时,CURL将标记此句柄但继续处理未处理的句柄,但这似乎不会发生.
当我们遇到错误的句柄时,CURL会将此句柄标记错误,但不会处理剩余的未处理句柄.

这可能很难检测,如果我确实得到了所有句柄的连接,这是大多数时间发生的事情,那么问题就不可见了.(CURL只在第一次错误连接时停止);

对于测试,我必须找到一个合适的站点,加载缓慢/拒绝x量同时连接.

set_time_limit(0);

$l = array(
    'http://smotri.com/video/list/','http://smotri.com/video/list/sports/','http://smotri.com/video/list/animals/','http://smotri.com/video/list/travel/','http://smotri.com/video/list/hobby/','http://smotri.com/video/list/gaming/','http://smotri.com/video/list/mult/','http://smotri.com/video/list/erotic/','http://smotri.com/video/list/auto/','http://smotri.com/video/list/humour/','http://smotri.com/video/list/film/'
);


$mh = curl_multi_init();

$s = 0;
$f = 10;

while($s <= $f)
{   

    $ch = curl_init();  

    $curlsettings = array(
        CURLOPT_URL => $l[$s],CURLOPT_TIMEOUT => 0,CURLOPT_CONNECTTIMEOUT => 0,CURLOPT_RETURNTRANSFER => 1
    );

    curl_setopt_array($ch,$curlsettings);
    curl_multi_add_handle($mh,$ch);

    $s++;

    }

$active = null;

do 
{
    curl_multi_exec($mh,$active);
    curl_multi_select($mh);

    $info = curl_multi_info_read($mh);

    echo '<pre>';
    var_dump($info);

    if($info['result'] === CURLE_OK)
        echo curl_getinfo($info['handle'],CURLINFO_EFFECTIVE_URL) . ' success<br>';

    if($info['result'] != 0)
        echo curl_getinfo($info['handle'],CURLINFO_EFFECTIVE_URL) . ' Failed<br>';

} while ($active > 0);

curl_multi_close($mh);

我在脚本中抛出了$info,询问Multi Handle是否在运行时有任何句柄的新信息.
当脚本结束时,我们将看到一些bool(false) – 当没有新信息可用时(句柄仍处理),以及所有句柄如果一切成功或有限句柄,如果一个句柄失败.

我没有解决这个问题,这可能是我忽略的事情,而且我试图修复那些不相关的东西,我已经走得太远了.

一些解决这个问题的尝试是.

>将每个$ch句柄分配给一个数组 – $ch [1],$ch [2]等(而不是
将当前$ch句柄添加到multi_handle然后覆盖 – 如何
在测试中)
>成功/失败后删除句柄
curl_ MULTI_ remove_处理
>将CURLOPT_CONNECTTIMEOUT和CURLOPT_TIMEOUT设置为无穷大.

>还有更多.(我会更新这篇文章,因为我已经忘记了所有这些)

使用PHP版本5.4.14进行测试
希望我已经很好地说明了这些观点.

谢谢阅读.

解决方法

我一直在尝试使用你的脚本一段时间试图让它工作.只有当我读到重复调用这个函数每次都会返回一个新的结果,直到返回一个FALSE作为一个信号,它有在这一点上没有更多内容.对于 http://se2.php.net/manual/en/function.curl-multi-info-read.php,我意识到while循环可能会起作用.

额外的while循环使其表现完全符合您的预期.这是我得到的输出

http://smotri.com/video/list/sports/ Failed

http://smotri.com/video/list/travel/ Failed

http://smotri.com/video/list/gaming/ Failed

http://smotri.com/video/list/erotic/ Failed

http://smotri.com/video/list/humour/ Failed

http://smotri.com/video/list/animals/ success

http://smotri.com/video/list/film/ success

http://smotri.com/video/list/auto/ success

http://smotri.com/video/list/ Failed

http://smotri.com/video/list/hobby/ Failed

http://smotri.com/video/list/mult/ Failed

这是我用于测试的代码

<?PHP
set_time_limit(0);

$l = array(
    'http://smotri.com/video/list/','http://smotri.com/video/list/film/'
);

$mh = curl_multi_init();

$s = 0;
$f = 10;

while($s <= $f)
{   
    $ch = curl_init();  

    if($s%2)
    {
        $curlsettings = array(
            CURLOPT_URL => $l[$s],CURLOPT_TIMEOUT_MS => 3000,CURLOPT_RETURNTRANSFER => 1,);
    }
    else
    {
        $curlsettings = array(
            CURLOPT_URL => $l[$s],CURLOPT_TIMEOUT_MS => 4000,);
    }

    curl_setopt_array($ch,$ch);
    $s++;
}

$active = null;

do 
{

    $mrc = curl_multi_exec($mh,$active);
    curl_multi_select($mh);

    while($info = curl_multi_info_read($mh))
    {
        echo '<pre>';
        //var_dump($info);

        if($info['result'] === 0)
        {
            echo curl_getinfo($info['handle'],CURLINFO_EFFECTIVE_URL) . ' success<br>';
        }
        else
        {
            echo curl_getinfo($info['handle'],CURLINFO_EFFECTIVE_URL) . ' Failed<br>';
        }   
    }

} while ($active > 0);

curl_multi_close($mh);

希望有所帮助.要进行测试,只需将CURLOPT_TIMEOUT_MS调整为您的互联网连接即可.我做到了这样它在3000到4000毫秒之间交替,因为3000将失败并且4000通常成功.

更新

在浏览了PHP和libCurl文档之后,我发现curl_multi_exec是如何工作的(在libCurl中它的curl_multi_perform).在第一次被调用时,它开始处理所有添加的句柄的传输(在通过curl_multi_add_handle之前添加).

它指定$活动的数字是仍在运行的转移数量.因此,如果它小于您拥有的句柄总数,那么您就知道一个或多个传输已完成.所以curl_multi_exec也是一种进度指标.

由于所有传输都以非阻塞方式处理(传输可以同时完成),因此while循环curl_multi_exec不能代表已完成的url请求的每次迭代.

所有数据都存储在队列中,因此只要完成一个或多个传输,您就可以调用curl_multi_info_read来获取此数据.

在我的原始答案中,我在while循环中使用了curl_multi_info_read.此循环将继续迭代,直到curl_multi_info_read在队列中找不到剩余数据.如果$active!= 0(意味着curl_multi_exec报告传输仍未完成),则外部while循环将移动到下一次迭代.

总而言之,当仍然没有完成传输时,外部循环继续迭代,并且内部循环仅在完成传输的数据时才进行迭代.

PHP文档对于curl多功能非常糟糕,所以我希望这清除了一些东西.下面是另一种做同样事情的方法.

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

// while($info = curl_multi_info_read($mh)) would work also here
for($i = 0; $i <= $f; $i++){
    $info = curl_multi_info_read($mh);

    if($info['result'] === 0)
    {
        echo curl_getinfo($info['handle'],CURLINFO_EFFECTIVE_URL) . ' success<br>';
    }
    else
    {
        echo curl_getinfo($info['handle'],CURLINFO_EFFECTIVE_URL) . ' Failed<br>';
    }
}

根据这些信息,您还可以看到不需要curl_multi_select,因为您不希望在有活动之前阻塞某些东西.

使用您在问题中提供的代码,似乎只有在几次传输失败后curl没有继续进行,但实际上仍有数据在缓冲区中排队.你的代码没有足够多次调用curl_multi_info_read.您的代码获取所有成功传输的原因是由于PHP在单个线程上运行,因此脚本挂起等待请求.失败请求的超时不足以使PHP挂起/等待那么长时间,因此while循环执行的迭代次数少于排队数据的次数.

猜你在找的Linux相关文章