首先我们先了解一下php curl
如果开启了IPv6,curl默认会优先解析 IPv6,在对应域名没有 IPv6 的情况下,会等待 IPv6 dns解析失败 timeout 之后才按以前的正常流程去找 IPv4
在程序中我对curl获取内容都作了较为严格的超时限制,所以就会造成无法获取内容的问题。
php的curl设置方法如下:
<?php
/**
* IPV6下curl超时问题
*/
$ch = curl_init();
curl_setopt ($ch, CURLOPT_URL, $url);
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, true);
//设置curl默认访问为IPv4
if(defined('CURLOPT_IPRESOLVE') && defined('CURL_IPRESOLVE_V4')){
curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
}
//设置curl请求连接时的最长秒数,如果设置为0,则无限
curl_setopt ($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
//设置curl总执行动作的最长秒数,如果设置为0,则无限
curl_setopt ($ch, CURLOPT_TIMEOUT,$timeout*3);
$file_contents = curl_exec($ch);
curl_close($ch);
以下是在网上搜索的一个实例:
$url = 'https://www.xxx.com/xxx.mp3';
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 20);
var_dump(curl_error($ch));
提示错误:SSL: certificate verification failed (result: 5)
然后网上搜了一大片:最多的解决方法是加上如下代码:
curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt ($ch, CURLOPT_SSL_VERIFYHOST, false);
加上之后又报错:
SSL: CA certificate set, but certificate verification is disabled
该如何解决????
<?php
$urls = [
"https://cdn.XXX.com/lion-2016620__340.jpg 1x,
https://cdn.XXX.com/lion-2016620__480.jpg",
"https://cdn.XXX.com/architecture-2083687__340.jpg 1x,
https://cdn.XXX.com/architecture-2083687__480.jpg",
"https://cdn.XXX.com/reptile-2042906__340.jpg 1x,
https://cdn.XXX.com/reptile-2042906__480.jpg"
];
foreach ($urls as $k => $v) {
if (!empty($v) && preg_match("~^http~i", $v)) {
$nurl[$k] = trim(str_replace(' ', "%20", $v));
$curl[$k] = curl_init($nurl[$k]);
curl_setopt($curl[$k], CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
curl_setopt($curl[$k], CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl[$k], CURLOPT_HEADER, 0);
curl_setopt($curl[$k], CURLOPT_CONNECTTIMEOUT, 20);
curl_setopt($curl[$k], CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl[$k], CURLOPT_SSL_VERIFYHOST, false);
if (!isset($handle)) {
$handle = curl_multi_init();
}
curl_multi_add_handle($handle, $curl[$k]);
}
continue;
}
$active = null;
do {
$mrc = @curl_multi_exec($handle, $active);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
while ($active && $mrc == CURLM_OK) {
if (curl_multi_select($handle) != -1) {
do {
$mrc = curl_multi_exec($handle, $active);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
}
}
foreach ($curl as $k => $v) {
var_dump(curl_error($curl[$k]));
}
以上解决方法按理来说应该没有问题,但依然报错。最后解决方法:
curl_setopt($curl[$k], CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
改成:
curl_setopt($curl[$k], CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V6);
原文地址https://segmentfault.com/q/1010000008502236