Вопрос по php, curl, yii – ОШИБКА CURL: Ошибка Recv: Сброс соединения по пиру - PHP Curl

56

У меня странная ошибка,CURL ERROR: Recv failure: Connection reset by peer

Вот как это происходит, если я не подключился к серверу и вдруг при попытке подключиться к серверу через CURL в PHP я получаю сообщение об ошибке. Когда я снова запускаю сценарий CURL, ошибка исчезает и все время работает хорошо, если я оставляю удаленный сервер бездействующим в течение 30 минут или перезагружаю удаленный сервер и пытаюсь подключиться снова, я снова получаю ошибку. Таким образом, кажется, что соединение бездействует, и вдруг сервер просыпается, затем работает, а затем снова спит.

Вот так выглядит мой скрипт CURL.

<code>$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);
</code>

У меня полностью нет идей и решений, пожалуйста, помогите, я буду признателен за это !!!

Если я подробный вывод, чтобы увидеть, что происходит с помощью

<code>curl_setopt ($c, CURLOPT_VERBOSE, TRUE);
curl_setopt($c, CURLOPT_STDERR, $fp); 
</code>

Я получаю следующее

<code>* 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
</code>

Я добавил следующий палец, чтобы удалить заголовок по умолчанию, но мне все равно не повезло:

<code>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
</code>
Что происходит, когда вы переходите по этому URL в вашем браузере? Explosion Pills
@Roland Существует также CURLOPT_SSL_VERIFYHOST, пожалуйста, попробуйте также установить значение false. alganet
URL-адрес http или https? При использовании HTTP вы должны убедиться, что CURL готов обработать его, используяCURLOPT_SSL_VERIFYPEER как ложь alganet
@Roland: попробуйте увеличить время ожидания соединения: curl_setopt ($ c, CURLOPT_CONNECTTIMEOUT, 10); Jens Bradler
@tandu - я не могу добавить весь URL-адрес в адресную строку, так как содержимое содержит много HTML-текста. Но когда я добавляю URL в браузер без значений POST, браузер нормально открывает страницу Roland

Ваш Ответ

6   ответов
3

Yii::app()->params['pdfUrl'] дает? Вы говорите, что это должен быть https, но в журнале показано, что он подключается через порт 80 ... на котором почти ни один сервер не настроен для приема подключений https. cURL достаточно умен, чтобы знать, что https должен быть на порту 443 ... что предполагает, что в вашем URL есть что-то необычное, например:https://196.41.139.168:80/serve/?r=pdf/generatePdf

Это приведет к разрыву соединения, когда Apache на другом конце не сможет установить связь https с вами через этот порт.

Вы понимаете, что ваш первый$body определение заменяется при установке$body массиву двумя строками позже? {Возможно, это просто артефакт того, что вы пытаетесь решить проблему} Вы также не кодируетеclient_url а такжеclient_id значения (первые, возможно, содержат символы, которые нужно экранировать!) О, и вы добавляете в$body_str без предварительной инициализации.

Из вашего подробного вывода мы видим, что cURL добавляетcontent-length заголовок, но ... это правильно? Я вижу, что некоторые комментарии о неправильных интернет-сетях этого числа (особенно в старых версиях) ... если это число слишком мало (например), вы получите сброс соединения перед отправкой всех данных. Вы можете вручную вставить заголовок:

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

Да, и есть удобная функцияhttp_build_query  который 'преобразует массив пар имя / значение в URL-кодированную строку для вас.

Все это сворачивается в окончательный код:

$post=http_build_q,uery(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);
0

Когда вы скручиваете страницу с определенным протоколом SSL.

curl --sslv3 https://example.com

Если --sslv3 не поддерживается целевым сервером, то ошибка будет

curl: (35) TCP connection reset by peer

С поддерживаемым протоколом ошибка исчезнет.

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

https://example.com - но они обеспечивают «www.» - поэтому, когда я переключился наhttps://www.example.com все было хорошо Надлежащий заголовок был отправлен «Хост: www.example.com».

Вы можете попытаться сделать запрос в firefox brwoser, сохранить его и скопировать как cURL - так я и нашел.

1

убедитесь, что брандмауэр на антивирусе выключен или разрешает подключения.

Если этот сервер находится в защищенной сети, ознакомьтесь с правилами брандмауэра сервера.

Спасибо Ганеш ПНС

10

что соединение было установлено с сервером, но это соединение было закрыто удаленным сервером. Это может быть связано с медленным сервером, проблемой с удаленным сервером, сетевыми проблемами или (может быть) какой-то ошибкой безопасности при отправке данных на удаленный сервер, но я считаю это маловероятным.

Обычно ошибка сети устраняется через некоторое время, но, похоже, вы уже дали ей немного времени.

cURL иногда имеет проблемы с SSL и SSL-сертификатами. Я думаю, что ваш Apache и / или PHP был скомпилирован с последней версией библиотек cURL и cURL SSL, плюс я не думаю, что OpenSSL был установлен на вашем веб-сервере.

Хотя я не могу быть уверен, однако, я полагаю, что cURL исторически был ненадежным с сертификатами SSL, тогда как Open SSL нет.

В любом случае, попробуйте установить Open SSL на сервер и попробуйте снова, и это должно помочь вам избавиться от этой ошибки.

91
Introduction

который указывает на немедленное прекращение соединения, а не на обычное рукопожатие.

Possible Causes

A.TCP/IP

Это может быть проблема TCP / IP, которую вам нужно решить с вашим хостом или обновить ОС. В большинстве случаев соединение закрывается до того, как удаленный сервер завершит загрузку контента, что приводит кConnection reset by peer.....

B.Kannel Bug

Обратите внимание, что есть некоторые проблемы с масштабированием окна TCP в некоторых ядрах Linux после v2.6.17. Смотрите следующие сообщения об ошибках для получения дополнительной информации:

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 Bug

Ты используешьPHP/5.3.3 у которого тоже есть серьезные ошибки ... я бы посоветовал вам поработать с более свежей версиейPHP а такжеCURL

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.Maximum Transmission Unit

Одной из распространенных причин этой ошибки является то, что размер пакетов MTU (Maximum Transmission Unit), передаваемых по сетевому соединению, был изменен по умолчанию на 1500 байтов. Если вы настроилиVPN это, скорее всего, должно быть изменено во время конфигурации

D.Firewall : iptables

Если вы не знаете, как обходиться с этими парнями, у них возникнут серьезные проблемы ... попробуйте получить доступ к серверу, к которому вы подключаетесь, чтобы проверить следующее

You have access to port 80 on that server

пример

 -A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT`
The Following is at the last line not before any other ACCEPT

пример

  -A RH-Firewall-1-INPUT -j REJECT --reject-with icmp-host-prohibited 

Check for ALL DROP , REJECT and make sure they are not blocking your connection

Temporary allow all connection as see if it foes through

Experiment

Попробуйте другой сервер или удаленный сервер (так много платных облачных хостингов в сети) и протестируйте один и тот же сценарий .. если он работает, то я думаю, что это так же хорошо, как правда ...You need to update your system

Others Code Related

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);

Я надеюсь, что это помогает

Так что есть брандмауэр :) Возможно, он устанавливает таймауты сессии не так, как веб-сервер.
Я не уверен ... у меня была проблема однажды ... после того, как я чуть не убил себя, я просто обновился, и все работало нормально .... Знаете, это может быть сумасшествием ... Рад, что я смог решить вашу проблему
Проблема, похоже, была решена, но проверим в ближайшие несколько дней, прежде чем я дам ответ. То, что я сделал, было следующим, но я не понимаю, почему это, похоже, решило проблему. Я ssh 'd на машине выполнил эту команду sudo iptables -L и затем остановка службы iptables службы sudo и затем запуск iptables службы sudo, когда я запустил остановку службы iptables sudo, она сбросила те iptables, которые я никогда не использовал, и внезапно проблема была решена , В iptables не было информации. Знаете ли вы, почему это решило проблему? Roland
@Roland .. хорошо, я подожду… я буду рад помочь, если у вас возникнут какие-либо проблемы
@Baba - я подтверждаю, действительно ли это сработало через несколько дней, и перезвоню вам, ребята Roland

Похожие вопросы