繁体   English   中英

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

[英]CURL ERROR: Recv failure: Connection reset by peer - PHP Curl

我遇到了这个奇怪的错误, 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

介绍

远程服务器向您发送了一个 RST 数据包,这表明连接立即断开,而不是通常的握手。

可能的原因

A. TCP/IP

这可能是 TCP/IP 问题,您需要与主机一起解决或升级您的操作系统,大多数时候连接在远程服务器完成下载内容之前关闭,导致对等Connection reset by peer .....

B. Kannel Bug

请注意,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 
  • 检查 ALL DROP , REJECT 并确保它们没有阻止您的连接

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

实验

尝试不同的服务器或远程服务器(网上有很多收费的云托管)并测试相同的脚本..如果它有效,那么我猜和真的一样好...... You need to update your system

其他代码相关

A. SSL

如果Yii::app()->params['pdfUrl']是一个带有https的 url 不包括正确的 SSL 设置也会在旧版本的 curl 中导致此错误

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

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

我希望它有帮助

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

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

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

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

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

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

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

当您在两行之后将$body设置$body数组时,您意识到您的第一个$body定义被替换了吗? {可能只是你试图解决问题的client_url }你也没有对client_urlclient_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);

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

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

curl --sslv3 https://example.com

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

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

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

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

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

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

感谢 Ganesh PNS

我们在与负载均衡器建立 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 网址...
  • 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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM