82

我遇到了这个奇怪的错误,CURL ERROR: Recv failure: Connection reset by peer

这就是它的发生方式,如果我没有连接到服务器并且突然尝试通过 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
4

7 回答 7

121

介绍

远程服务器向您发送了一个 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 & CURL 错误

您正在使用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`
  • 以下是在最后一行而不是在任何其他 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']是一个https不包含正确 SSL 设置的 url,也会在旧版本的 curl 中导致此错误

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

curl_setopt($c, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($c, CURLOPT_SSL_VERIFYHOST, false);
于 2012-04-27T11:35:01.627 回答
18

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

通常,网络错误会在一段时间内自行解决,但听起来您已经给了它一点时间。

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

虽然我不能确定但是,我相信 cURL 在历史上一直使用 SSL 证书,而 Open SSL 没有。

无论如何,尝试在服务器上安装 Open SSL 并重试,这应该可以帮助您摆脱此错误。

于 2012-04-30T18:00:54.270 回答
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);
于 2012-04-27T17:31:24.593 回答
4

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

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

curl --sslv3 https://example.com

如果目标服务器不支持 --sslv3 则错误将是

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

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

curl --tlsv1.2 https://example.com
于 2018-03-19T19:44:18.987 回答
2

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

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

谢谢 Ganesh PNS

于 2015-10-13T05:30:47.867 回答
1

在与负载均衡器建立 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 Host: localhost User-Agent: curl/7.60.0 Accept: / Connection: Upgrade Upgrade: websocket Origin: http://LB URL:80

  • 接收失败:对等方重置连接
  • 关闭连接 0 curl: (56) Recv failure: Connection reset by peer
于 2019-12-04T05:31:46.507 回答
0

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

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

于 2016-02-04T20:59:09.253 回答