CURL错误:接收失败:对等连接重置-PHP Curl


69

我遇到这个奇怪的错误,CURL错误:接收失败:对等连接重置

如果我没有连接到服务器,而突然尝试通过PHP中的CURL连接到服务器,则会发生此错误。当我再次运行CURL脚本时,错误消失,然后在整个过程中都正常运行,如果我将远程服务器保持空闲状态约30分钟或重新启动远程服务器并尝试重新连接,则我会再次收到该错误。因此,似乎连接处于空闲状态,然后突然服务器唤醒,然后工作,然后再次休眠。

这就是我的CURL脚本的外观。

$url = Yii::app()->params['pdfUrl'];
            $body = 'title='.urlencode($title).'&client_url='.Yii::app()->params['pdfClientURL'].'&client_id='.Yii::app()->params['pdfClientID'].'&content='.urlencode(htmlentities($content));

            $c = curl_init ($url);
            $body = array(
                "client_url"=>Yii::app()->params['pdfClientURL'],
                "client_id"=>Yii::app()->params['pdfClientID'],
                "title"=>urlencode($title),
                "content"=>urlencode($content)

            );
            foreach($body as $key=>$value) { $body_str .= $key.'='.$value.'&'; }
                rtrim($body_str,'&');

            curl_setopt ($c, CURLOPT_POST, true);
            curl_setopt ($c, CURLOPT_POSTFIELDS, $body_str);
            curl_setopt ($c, CURLOPT_RETURNTRANSFER, true);
            curl_setopt ($c, CURLOPT_CONNECTTIMEOUT , 0);
            curl_setopt ($c, CURLOPT_TIMEOUT  , 20);

            $pdf = curl_exec ($c);
            $errorCode = curl_getinfo($c, CURLINFO_HTTP_CODE);
            $curlInfo = curl_getinfo($c);
            $curlError = curl_error($c);

            curl_close ($c);

我完全没有想法和解决方案,请帮忙,我将不胜感激!!!

如果我详细输出以查看使用会发生什么

curl_setopt ($c, CURLOPT_VERBOSE, TRUE);
curl_setopt($c, CURLOPT_STDERR, $fp); 

我得到以下

* About to connect() to 196.41.139.168 port 80 (#0)
*   Trying 196.x.x.x... * connected
* Connected to 196.x.x.x (196.x.x.x) port 80 (#0)
> POST /serve/?r=pdf/generatePdf HTTP/1.1
Host: 196.x.x.x
Accept: */*
Content-Length: 7115
Content-Type: application/x-www-form-urlencoded
Expect: 100-continue

* Recv failure: Connection reset by peer
* Closing connection #0
012 20:23:49 GMT
< Server: Apache/2.2.15 (CentOS)
< X-Powered-By: PHP/5.3.3
< Connection: close
< Transfer-Encoding: chunked
< Content-Type: text/html; charset=UTF-8
< 
* Closing connection #0

我在以下脚趾中添加了默认标题,但仍然没有运气:

curl_setopt ($c, CURLOPT_HTTPHEADER, array( 'Expect:' ) );

> Accept: */* Content-Length: 8414 Content-Type:
> application/x-www-form-urlencoded
> 
> * Recv failure: Connection reset by peer
> * Closing connection #0 r: Apache/2.2.15 (CentOS) < X-Powered-By: PHP/5.3.3 < Connection: close < Transfer-Encoding: chunked <
> Content-Type: text/html; charset=UTF-8 < 
> * Closing connection #0

当您在浏览器中转到该URL时会发生什么?
爆炸药2012年

@tandu-我无法将整个URL添加到地址栏中,因为内容是很多HTML文本。但是,当我将网址添加到没有POST值的浏览器中时,浏览器可以正常打开页面
Elitmiar 2012年

URL是http还是https?使用HTTP时,应确保CURL准备好使用CURLOPT_SSL_VERIFYPEERfalse来处理它。
alganet 2012年

1
@Roland还有一个CURLOPT_SSL_VERIFYHOST,也请尝试将其设置为false。
alganet

1
@Roland:请尝试增加连接超时:curl_setopt($ c,CURLOPT_CONNECTTIMEOUT,10);
詹斯·布拉德勒

Answers:


110

介绍

远程服务器已向您发送了RST数据包,该数据包指示立即断开连接,而不是通常的握手。

可能的原因

A. TCP / IP

这可能是TCP / IP问题,您通常需要与主机一起解决或升级操作系统,通常在远程服务器关闭连接之前,它才完成将内容下载到Connection reset by peer.....的操作。

B.康奈尔虫子

请注意,在v2.6.17之后,某些Linux内核上的TCP窗口缩放存在一些问题。有关更多信息,请参见以下错误报告:

https://bugs.launchpad.net/ubuntu/+source/linux-source-2.6.17/+bug/59331

https://bugs.launchpad.net/ubuntu/+source/linux-source-2.6.20/+bug/89160

C. PHP和卷曲的Bug

您正在使用的工具PHP/5.3.3也存在一些严重的错误...我建议您使用较新版本的PHPCURL

https://bugs.php.net/bug.php?id=52828

https://bugs.php.net/bug.php?id=52827

https://bugs.php.net/bug.php?id=52202

https://bugs.php.net/bug.php?id=50410

D.最大传输单位

导致此错误的一个常见原因是,通过网络连接传输的数据包的MTU(最大传输单元)大小已从默认的1500字节更改。如果已配置,VPN则很可能必须在配置期间进行更改

D.防火墙:iptables

如果您不知道如何解决这些问题,可能会导致一些严重的问题..尝试访问您要连接的服务器以检查以下内容

  • 您可以访问该服务器上的端口80

 -A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT`
  • 以下是最后一行,而不是其他任何接受之前

  -A RH-Firewall-1-INPUT -j REJECT --reject-with icmp-host-prohibited 
  • 检查所有DROP,REJECT并确保它们没有阻止您的连接

  • 暂时允许所有连接,看是否通过

实验

尝试使用其他服务器或远程服务器(在线托管如此多的费用云)并测试相同的脚本..如果它可以工作,那么我猜是一样的不错... You need to update your system

其他代码相关

A. SSL

如果Yii::app()->params['pdfUrl']url中https未包含正确的SSL设置,则在旧版本的curl中也会导致此错误

解决方法:确保已安装并启用了OpenSSL,然后将其添加到您的代码中

curl_setopt($c, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($c, CURLOPT_SSL_VERIFYHOST, false);

希望对您有所帮助


1
该问题似乎已经得到解决,但是在接下来的几天中我将进行检查,然后再给出答案。我所做的是以下操作,但我不明白为什么这似乎可以解决问题。我向机器运行了此命令sudo iptables -L,然后sudo服务iptables停止,然后sudo服务iptables启动,当我运行sudo service iptables停止时,它刷新了我从未使用过的iptables,一下子解决了问题。iptables中没有信息。您是否知道为什么这可以解决问题
Elitmiar 2012年

因此,这里有一个防火墙:)它可能会强制执行与Web服务器不同的会话超时。
EricM 2012年

不确定..我曾经遇到问题...几乎自杀后,我刚刚升级,一切都正常....这件事可能很疯狂,您知道.. Am Glad我能够解决您的问题
爸爸

@Baba-我将在几天后确认它是否真的起作用,然后再回头给大家
Elitmiar 2012年

@Roland ..好的,我将等待..如果您有任何其他问题,我将很乐意为您提供帮助
Baba

16

通常,此错误表示已与服务器建立连接,但该连接已由远程服务器关闭。这可能是由于服务器速度慢,远程服务器出现问题,网络出现问题,或者(可能)由于将数据发送到远程服务器而导致的某种安全性错误,但我认为这不太可能。

通常,网络错误会在一段时间后解决,但听起来您已经花了一些时间。

cURL有时与SSL和SSL证书有关。我认为您的Apache和/或PHP是使用cURL和cURL SSL库的最新版本编译的,而且我认为您的Web服务器中未安装OpenSSL。

尽管我不确定,但是,我相信cURL历来都是SSL证书,而Open SSL并非如此。

无论如何,请尝试在服务器上安装Open SSL,然后重试,这将帮助您摆脱此错误。


4

那么Yii::app()->params['pdfUrl']给出的URL是什么?您说应该是https,但是日志显示它正在端口80上连接...几乎没有服务器设置为接受https连接。cURL足够聪明,可以知道https应该在端口443上。这表明您的URL有点奇怪:https://196.41.139.168:80/serve/?r=pdf/generatePdf

当另一端的Apache无法在该端口上与您进行https通信时,这将导致连接终止。

您意识到在两行后$body设置$body为数组时会替换第一个定义吗?{可能只是您尝试解决问题的人工工具}您也不在对client_urlandclient_id值进行编码(前者很可能包含需要转义的字符!)哦,您将在$body_str不首先对其进行初始化的情况下进行附加。

从您的详细输出中,我们可以看到cURL正在添加content-length标头,但是...正确吗?我可以在互联网上看到一些评论,指出该数字是错误的(尤其是旧版本)...如果该数字很小(例如),您将在发送所有数据之前进行连接重置。您可以手动插入标题:

curl_setopt ($c, CURLOPT_HTTPHEADER, 
   array("Content-Length: ". strlen($body_str))); 

哦,有一个方便的函数http_build_query 可以将名称/值对的数组转换为适合您的URL编码的字符串。

所有这些汇总到最终代码中:

$post=http_build_query(array(
  "client_url"=>Yii::app()->params['pdfClientURL'],
  "client_id"=>Yii::app()->params['pdfClientID'],
  "title"=>$title,
  "content"=>$content));

//Open to URL
$c=curl_init(Yii::app()->params['pdfUrl']);
//Send post
curl_setopt ($c, CURLOPT_POST, true);
//Optional: [try with/without]
curl_setopt ($c, CURLOPT_HTTPHEADER, array("Content-Length: ".strlen($post))); 
curl_setopt ($c, CURLOPT_POSTFIELDS, $post);
curl_setopt ($c, CURLOPT_RETURNTRANSFER, true);
curl_setopt ($c, CURLOPT_CONNECTTIMEOUT , 0);
curl_setopt ($c, CURLOPT_TIMEOUT  , 20);
//Collect result
$pdf = curl_exec ($c);
$curlInfo = curl_getinfo($c);
curl_close($c);

3

我遇到了相同的错误,但是方式不同。

使用特定的SSL协议卷曲页面时。

curl --sslv3 https://example.com

如果目标服务器不支持--sslv3,则错误为

curl:(35)对等方重置TCP连接

使用支持的协议,错误将消失。

curl --tlsv1.2 https://example.com

2

这是一个防火墙问题,如果您使用的是VMware应用程序,请确保防病毒软件上的防火墙已关闭或允许连接。

如果此服务器位于安全网络上,请查看服务器的防火墙规则。

感谢Ganesh PNS


0

就我而言,URL有问题。我使用了https://example.com-但它们确保使用“ www”。-所以当我切换到https://www.example.com时,一切都很好。正确的标头已发送给“主机:www.example.com”。

您可以尝试在firefox brwoser中发出请求,将其保留并复制为cURL-这就是我如何找到它。


0

在与负载均衡器建立websocket连接时,我们遇到了同样的问题。问题出在LB中,接受端口80上的http连接并将请求转发到节点(端口8080上的tomcat应用)。我们已将其更改为在端口80上接受tcp(http已更改为“ tcp”)连接。因此,第一个握手请求被转发到Node,并成功以某种随机方式成功建立了websocket连接(据我所知,可能是错误)端口。

下面的命令已用于测试websocket握手过程。

curl -v -i -N -H "Connection: Upgrade" -H "Upgrade: websocket" -H "Host: localhost" -H "Origin: http://LB URL:80" http://LB URL

  • 将URL重建为:http:LB URL /
  • 正在尝试LB URL ...
  • TCP_NODELAY设置
  • 连接到LB URL(LB URL)端口80(#0)

    GET / HTTP / 1.1主机:localhost用户代理:curl / 7.60.0接受:/ 连接:升级升级:websocket来源:http:// LB URL:80

  • 接收失败:对等连接重置
  • 关闭连接0 curl:(56)接收失败:连接被对等方重置
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.