curl_exec区分超时原因

时间:2015-10-23 18:09:23

标签: php php-curl

在PHP中,curl_exec有多个选项可用于中止花费时间过长的请求CURLOPT_TIMEOUTCURLOPT_CONNECTTIMEOUTCURLOPT_LOW_SPEED_TIME等。我相信所有这些情况的errno是28(这只表示操作超时),libcurl是否根据达到的超时报告任何不同的内容,并且PHP是否公开了这个功能?

我尝试在简单的PHP函数上更改这些选项的值,但是无法生成非28错误。

function curl_test() {

    $ch = curl_init();

    $options = array(
        CURLOPT_URL => 'http://www.google.com',
        CURLOPT_HEADER => false,
        CURLOPT_TIMEOUT_MS => 1000,
        CURLOPT_CONNECTTIMEOUT_MS => 10,
    );

    curl_setopt_array($ch, $options);

    curl_exec($ch);

    $out = curl_errno($ch);
    curl_close($ch);
    return $out;
}

1 个答案:

答案 0 :(得分:1)

为了实现这一目标,我认为我们只需要测试我们正在寻找的Timeout。所以我看到以下场景:

  1. 超时连接到URL(连接超时 - 主机关闭)
  2. 执行操作超时(操作超时)
  3. 由于连接速度慢(低速时间)导致超时
  4. 我们可以使用其他方法检查第一次超时。所以我们这样做:

    <?php
    $site="http://www.google.com";
    $content = file_get_contents($site);
    if($content === false){
        // Host dead, handle error here...
    }
    ?>
    

    参考:How can I handle the warning of file_get_contents() function in PHP?

    此时,我们知道我们不应该获得连接超时。我们可以继续执行curl并知道它将是一个操作超时或速度。

    <?php
    function curl_run($opts){
        $content = file_get_contents($opts[CURLOPT_URL]);
        if($content === false){
            return false;
        } else {
            $resp = array();
            $time_start = microtime(true);
            $ch = curl_init();
            curl_setopt_array($ch, $opts);
            $resp['result'] = curl_exec($ch);
            $time_end = microtime(true);
            $resp['info'] = curl_getinfo($ch);
            if(curl_errno($ch)){
                $resp['error'] = curl_error($ch);
            }
            curl_close($ch);
            $resp['time'] = $time_end - $time_start; // Time it took
            return $resp;
        }
    }
    
    $url = isset($_GET['url'])?$_GET['url']:"http://www.google.com/";
    $options = array(
            CURLOPT_URL => $url,
            CURLOPT_HEADER => true,
            CURLOPT_TIMEOUT_MS => 1000,
            CURLOPT_CONNECTTIMEOUT_MS => 10,
            CURLOPT_RETURNTRANSFER => 1,
            CURLOPT_VERBOSE => 1
    );
    
    $results = curl_run($options);
    if($results){
            echo "<h2>Options</h2>\r\n";
            echo "<pre>";
            foreach($options as $k => $v){
                    echo "$k: $v\r\n";
            }
            echo "</pre>";
            echo "<h2>Info</h2>\r\n";
            echo "<pre>";
            foreach($results['info'] as $k => $v){
                    echo "$k: $v\r\n";
            }
            echo "time: {$results['time']}\r\n";
            echo "</pre>\r\n";
            if(isset($results['error'])){
                    echo "<h2>Error</h2>\r\n";
                    echo "<pre>{$results['error']}</pre>\r\n";
            }
            echo "<h2>Response</h2>\r\n";
            echo "<pre>" . htmlentities($results['result']) . "</pre>";
    }
    ?>
    

    我们应该能够查看所有这些并确定执行操作所花费的时间是否接近我们的超时设置之一。否则我们也会在info下拥有大量数据。如果返回false,我们知道主机无法访问。

    进行了进一步测试,您可以在此处查看:http://www.yrmailfrom.me/projects/php/curl_test1.php?url=http://www.apple.com/

    我发现Apple.com花了14毫秒,所以它成了一个很好的测试。

    示例输出:

    Options
    
    10002: http://www.apple.com/
    42: 1
    155: 1000
    156: 10
    19913: 1
    41: 1
    
    Info
    
    url: http://www.apple.com/
    content_type: 
    http_code: 0
    header_size: 0
    request_size: 0
    filetime: -1
    ssl_verify_result: 0
    redirect_count: 0
    total_time: 0.014634
    namelookup_time: 0.004297
    connect_time: 0
    pretransfer_time: 0
    size_upload: 0
    size_download: 0
    speed_download: 0
    speed_upload: 0
    download_content_length: -1
    upload_content_length: -1
    starttransfer_time: 0
    redirect_time: 0
    redirect_url: 
    primary_ip: 
    certinfo: Array
    primary_port: 0
    local_ip: 
    local_port: 0
    time: 0.014760017395
    
    Error
    
    Connection timed out after 14 milliseconds
    
    Response