PHP捕获cURL CURLOPT_TIMEOUT和CURLOPT_CONNECTTIMEOUT事件并采取措施

时间:2012-08-27 07:43:49

标签: php events curl

我希望在检测到CURLOPT_CONNECTTIMEOUT和CURLOPT_TIMEOUT时检测,捕捉并执行某些操作。

我该怎么做?

我有以下标题:

public static $userAgents = array(
    'FireFox3' => 'Mozilla/5.0 (Windows; U; Windows NT 5.1; pl; rv:1.9) Gecko/2008052906 Firefox/3.0',
    'GoogleBot' => 'Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)',
    'IE7' => 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)',
    'Netscape' => 'Mozilla/4.8 [en] (Windows NT 6.0; U)',
    'Opera' => 'Opera/9.25 (Windows NT 6.0; U; en)'
);
public static $options = array(
    CURLOPT_USERAGENT => 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)',
    CURLOPT_AUTOREFERER => true,
    CURLOPT_FOLLOWLOCATION => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_FRESH_CONNECT => true,
    CURLOPT_COOKIEJAR => "cookies.txt",
    CURLOPT_COOKIEFILE => "cookies.txt",
    CURLOPT_SSL_VERIFYPEER => false,
    CURLOPT_CONNECTTIMEOUT => 5,
    CURLOPT_TIMEOUT => 300,
        //CURLOPT_COOKIESESSION => false,
);

以及下面的函数,其中$ res是一个包含html文件名的数组

public function multiCurl($res, $options = "") {

    if (count($res) <= 0)
        return False;

    $handles = array();

    if (!$options) // add default options
        $options = self::$options;

    // add curl options to each handle
    foreach ($res as $k => $row) {
        $ch{$k} = curl_init();
        $options[CURLOPT_URL] = $row['url'];
        curl_setopt_array($ch{$k}, $options);
        $handles[$k] = $ch{$k};
    }

    $mh = curl_multi_init();

    foreach ($handles as $k => $handle) {
        curl_multi_add_handle($mh, $handle);
    }

    $running_handles = null;
    //execute the handles
    do {
        $status_cme = curl_multi_exec($mh, $running_handles);
    } while ($cme == CURLM_CALL_MULTI_PERFORM);

    while ($running_handles && $status_cme == CURLM_OK) {
        if (curl_multi_select($mh) != -1) {
            do {
                $status_cme = curl_multi_exec($mh, $running_handles);
            } while ($status == CURLM_CALL_MULTI_PERFORM);
        }
    }

    foreach ($res as $k => $row) {
        $res[$k]['error'] = curl_error($handles[$k]);
        if (!empty($res[$k]['error']))
            $res[$k]['data'] = '';
        else {
            //$res[$k]['data'] = curl_multi_getcontent($handles[$k]);  // get results 
            file_put_contents(CRAWLER_FILES . $k . '.html', curl_multi_getcontent($handles[$k]));
        }

        // close current handler
        curl_multi_remove_handle($mh, $handles[$k]);
    }
    curl_multi_close($mh);
    return $res; // return response
}

3 个答案:

答案 0 :(得分:3)

要获取有关请求的信息,您可以查看curl_getinfocurl_multi_info_read

使用类似的东西:

curl_exec($ch);
if(!curl_errno($ch))
{
 $info = curl_getinfo($ch);
 echo 'Took ' . $info['total_time'] . ' seconds to send a request to ' . $info['url'];
}

在信息数组中,您可以收到以下数据:

  • “URL”
  • “CONTENT_TYPE”
  • “HTTP_CODE”
  • “header_size”
  • “request_size”
  • “FILETIME”
  • “ssl_verify_result”
  • “redirect_count”
  • “TOTAL_TIME”
  • “namelookup_time”
  • “CONNECT_TIME”
  • “pretransfer_time”
  • “size_upload”
  • “size_download”
  • “speed_download”
  • “speed_upload”
  • “download_content_length”
  • “upload_content_length”
  • “starttransfer_time”
  • “redirect_time”
  • “certinfo”
  • “request_header” (仅当CURLINFO_HEADER_OUT由前一个设置时才设置此项 调用curl_setopt())

答案 1 :(得分:3)

您有两个选择:

  1. 在从curl_getinfo($ch)返回的数组中,将connect_time与您用于CURLOPT_CONNECTTIMEOUT选项的值进行比较。您还可以将total_time与您用于CURLOPT_TIMEOUT的值进行比较。如果你转出curl_getinfo($ch),你会看到还有很多其他的计时器,你可以推断出你需要的任何东西。
  2. 使用从curl_error($ch)返回的字符串。如果您的任何*_TIMEOUT选项被点击,则会返回如下字符串:
  3.   

    操作在2001毫秒后收到0字节后超时

答案 2 :(得分:1)

您可以使用以下功能尝试连接3次,如果不成功则停止。每次尝试都会增加超时时间,以防万一服务器是&#34; FULL&#34;只需要一点时间。

public function functionName($attempt = 0) {
    if ($attemp >= 3) {
        return FALSE;
    }
    $TIMEOUT = 1;
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $TIMEOUT + $attempt);
    curl_exec($ch);
    if (!curl_errno($ch)) {
        $info = curl_getinfo($ch);
        if ($info['total_time'] > $TIMEOUT) {
            $this->functionName($attempt++);
        } else {
            return TRUE;
        }
    }
}