我有一个PHP脚本通过cURL连接到URL,然后根据返回的HTTP状态代码执行某些操作:
$ch = curl_init();
$options = array(
CURLOPT_RETURNTRANSFER => true,
CURLOPT_URL => $url,
CURLOPT_USERAGENT => "What?!?"
);
curl_setopt_array($ch, $options);
$out = curl_exec($ch);
$code = curl_getinfo($ch)["http_code"];
curl_close($ch);
if ($code == "200") {
echo "200";
} else {
echo "not 200";
}
有些网络服务器的回复速度很慢,而虽然页面在我的浏览器中加载了几秒钟我的脚本,当它尝试连接到该服务器时,告诉我它没有收到积极的(" 200")回复。所以,显然,cURL发起的连接超时了。
但为什么呢?我没有在脚本中设置超时,根据other answers on this site,cURL的默认超时肯定比在浏览器中加载页面所需的三到四秒长。
那么为什么连接会超时,如果显然已经设置为无限,我怎样才能让它更长久?
注意:
curl_getinfo($ch)
和curl_error($ch)
- 根据评论中的@ drew010建议 - 但每当问题发生时两者都是空的。更新
关注@ Karlos'在他的回答中提出建议,我用过:
CURLOPT_VERBOSE => 1,
CURLOPT_STDERR => $curl_log
(使用this answer中的代码)并在网址失败时更改了$curl_log
中的以下内容(网址和IP已更改):
* About to connect() to www.somesite.com port 80 (#0)
* Trying 104.16.37.249... * connected
* Connected to www.somesite.com (104.16.37.249) port 80 (#0)
GET /wp_german/?feed=rss2 HTTP/1.1
User-Agent: myURL
Host: www.somesite.com
Accept: */*
* Recv failure: Connection reset by peer
* Closing connection #0
所以,我找到了为什么 - 谢谢@Karlos! - 显然@Axalix是对的,这是一个网络问题。我现在将遵循本网站上针对此类失败提出的建议。感谢大家的帮助!
答案 0 :(得分:4)
我使用curl的经验告诉我,有时使用选项:
CURLOPT_RETURNTRANSFER => true
服务器可能无法成功回复,或者至少在 curl 必须接收响应并缓存它的时间范围内成功回复,因此结果将由curl返回到你指定的变量。在您的代码中:
$out = curl_exec($ch);
在此stackoverflow问题CURLOPT_RETURNTRANSFER set to true doesnt work on hosting server中,您可以看到选项CURLOPT_RETURNTRANSFER直接受请求的主机Web服务器实现的影响。
当您明确使用响应主体,并且您的代码依赖于响应头时,解决此问题的好方法可能是:
CURLOPT_RETURNTRANSFER => false
并执行curl代码以处理响应标头。
一旦你有了你感兴趣的代码的标题,就可以运行一个回复curl响应的php脚本并自己解析它:
<?php
$url=isset($_GET['url']) ? $_GET['url'] : 'http://www.example.com';
$ch= curl_init();
$options = array(
CURLOPT_RETURNTRANSFER => false,
CURLOPT_URL => $url,
CURLOPT_USERAGENT => "myURL"
);
curl_setopt_array($ch, $options);
curl_exec($ch);
curl_close($ch);
?>
在任何情况下,回复您的问题为什么您的请求都不会出错,我想使用选项 CURLOPT_NOSIGNAL 以及不同的超时选项在set_opt php manual可能会让你更接近它。
为了进一步挖掘,选项 CURLOPT_VERBOSE 可能会帮助您通过STDERR获得有关请求行为的额外信息。
答案 1 :(得分:0)
原因可能是您的托管服务提供商对传出连接施加了一些限制。
以下是保护脚本的方法:
在DB中创建一个包含所有需要提取的URL的队列。
每分钟或5分钟运行cron
,从数据库中取一些网址 - 将其标记为in progress
。
尝试获取这些网址。在DB中将每个提取的网址标记为success
。
增加失败计数的失败次数。
继续通过队列,直到它为空。
如果您实施此类解决方案,您将能够在任何不利条件下处理每个网址。