cURL 并发访问

通常情况下 PHP 中的 cURL 是阻塞运行的,就是说创建一个 cURL 请求以后必须等它执行成功或者超时才会执行下一个请求,curl_multi_* 系列函数使并发访问成功可能,PHP 文档对这个函数的介绍不太详细,用法如下:

$requests = array('http://zz.dongsheng.org', 'http://www.google.com');
$main    = curl_multi_init();
$results = array();
$errors  = array();
$info    = array();
$count   = count($requests);
for($i = 0; $i < $count; $i++) {
  $handles[$i] = curl_init($requests[$i]);
  var_dump($requests[$i]);
  curl_setopt($handles[$i], CURLOPT_URL, $requests[$i]);
  curl_setopt($handles[$i], CURLOPT_RETURNTRANSFER, 1);
  curl_multi_add_handle($main, $handles[$i]);
}
$running = 0;

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

for($i = 0; $i < $count; $i++)
{
  $results[] = curl_multi_getcontent($handles[$i]);
  $errors[]  = curl_error($handles[$i]);
  $info[]    = curl_getinfo($handles[$i]);
  curl_multi_remove_handle($main, $handles[$i]);
}
curl_multi_close($main);
var_dump($results);
var_dump($errors);
var_dump($info);

通过这种方式就可以实现多任务并发执行,更详细的用法看我写的这个类:curl class

7 Responses to “cURL 并发访问”

  1. Ven says:

    如何获得每个handle的错误信息呢?curl_error()在非并行时是正常的,并行时就不好用了。

  2. Ven says:

    测试了一下,并不起作用,比如把第二个链接改成”www.google”,errorcode是0。
    从php手册上找到了这个:,难道说这就是个bug?

  3. Hi, Ven
    我又测试了一下,第一地址 zz.dongsheng.org 返回了错误 Couldn’t resolve host zz.dongsheng.org
    PHP 文档里的 comment 已经很老了是 07 年的,可能新版的 PHP 已经修复了这个错误,我现在用的是 5.2.8,你用的是什么版本呢?

  4. Ven says:

    汗~~~5.2.6,回头升级到最新版试试。

  5. Ven says:

    找到原因了,似乎跟使用者网络环境有关。
    由于curl_error()对301、404等http错误不做反应,所以如果使用者的网络对错误的域名返回http错误码的话,curl_error()自然不会有值。
    相当扯淡,因为我这里有电信劫持的问题,所有无法解析的域名都被劫持到114的一个页面上了,所以对于”http://www.google”、”zz.dongsheng.org”这一类本来是错误的域名,却被电信劫持弄成了“正常的”网页。而在我的虚拟主机上,主机自动对无法解析的域名返回301,所以同样不会有curl_error()。
    似乎是这样,望CDS给予指正或补充。

  6. Ven says:

    找到原因了,不是curl的问题,和使用者的网络环境有关系。
    首先curl_error()是不对http错误作反应的。有些地方的网络对于错误的域名返回一个301(我的博客空间就是这样),这样curl_error()就没有返回值。而我本地有电信劫持问题,错误的域名会被劫持到114的网站上,那么自然也不存在错误了。
    望CDS给予指正。
    非常感谢您的耐心解答。

Leave a Reply