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

У меня странная ошибка, ОШИБКА CURL: Ошибка Recv: Сброс соединения по пиру

Вот как это происходит, если я не подключился к серверу и вдруг при попытке подключиться к серверу через CURL в PHP я получаю сообщение об ошибке. Когда я снова запускаю сценарий 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

11 ответов

Решение

Вступление

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

Возможные причины

А. 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

Ты используешь 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. Максимальная единица передачи

Одной из распространенных причин этой ошибки является то, что размер 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, ОТКЛОНИТЬ и убедитесь, что они не блокируют ваше соединение

  • Временно разрешите все соединения, как если бы они проходили

эксперимент

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

Другие, связанные с кодом

А. SSL

Если Yii::app()->params['pdfUrl'] это URL с https не правильная настройка 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, плюс я не думаю, что OpenSSL был установлен на вашем веб-сервере.

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

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

Я столкнулся с той же ошибкой, но по-другому.

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

curl --sslv3 https://example.com

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

curl: (35) TCP-соединение сбрасывается одноранговым

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

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

Так что URL, который 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_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);

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

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

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

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

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

У нас была такая же проблема при подключении веб-сокета к балансировщику нагрузки. Проблема заключается в LB, принимающем http-соединение на порт 80 и перенаправляющем запрос на узел (приложение tomcat на порту 8080). Мы изменили это, чтобы принимать tcp-соединение (http было изменено на 'tcp') на порт 80. Таким образом, первый запрос рукопожатия перенаправляется на узел, и соединение через веб-сокет выполняется успешно на некотором случайном (насколько я знаю, может быть неправильно) порт.

Команда ниже была использована для тестирования процесса рукопожатия веб-сокета.

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/
  • Пробуем 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

  • Ошибка Recv: сброс соединения одноранговым узлом
  • Закрытие соединения 0 curl: (56) Ошибка Recv: сброс соединения одноранговым узлом

В одном из приложений я внезапно увидел следующий ответ.

      56 Recv failure: Connection reset by peer

Мне удалось сделать запрос к конечной точке с помощью Curl.

      curl -i http://example.com/ws/soap?wsdl

Также, используя SoapUI, мне удалось получить ответ. Но, используя код Php для выполнения запроса на завивку, я получил ошибку 56 Recv: сброс соединения по одноранговому узлу.

Я проверил журналы программного обеспечения безопасности и журналы WAF, но ничего не нашел.

У меня был такой код

      $curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $wsdl);
curl_setopt($curl, CURLOPT_VERBOSE, 0); 
curl_setopt($curl, CURLOPT_HTTPHEADER, $headerArr);
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, $requestXml);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);  
curl_setopt($curl, CURLOPT_CONNECTTIMEOUT ,0); 
curl_setopt($curl, CURLOPT_TIMEOUT, 400);

$response = curl_exec($curl);
curl_close($curl);

Где я передал следующий заголовок

      $headerArr = array('Content-Type: text/xml;charset=UTF-8',
                    'SOAPAction: http://sap.com/xi/WebService/soap1.1',
                    'User-Agent: PHP-SOAP/5.2.9-2',
                    'Host: http://example.com/ws/soap?wsdl');
                

Из-за некоторого обновления некоторые настройки на стороне целевого приложения изменились. После изменения хоста с http://example.com/ws/soap?wsdlhttp://example.com/ws/soap?wsdl на example.com проблема была устранена.

      $headerArr = array('Content-Type: text/xml;charset=UTF-8',
                    'SOAPAction: http://sap.com/xi/WebService/soap1.1',
                    'User-Agent: PHP-SOAP/5.2.9-2',
                    'Host: example.com');

Поэтому всегда старайтесь отредактировать и заголовок, если вы не можете найти причину другими способами.

Это может быть связано с тем, что ваши TCP-соединения, созданные запросами на завивку, не закрываются после завершения задания. Это может привести к увеличению количества рабочих_соединений, которые может удерживать процесс Nginx, и привести к тому, что сервер nginx сбросит новые соединения.

Один из способов избежать этой проблемы — добавить флаги --retry и --retry-all-errors (доступные в последних версиях Curl) в ваш запрос на завивку, чтобы ваш завиток повторял попытку даже в случае сброса соединения одноранговым узлом. Также увеличение количества рабочих_соединений в файле nginx.conf также может помочь вам избежать достижения максимального предела TCP-соединений.

Попробуйте закрыть все открытые TCP-соединения, как только запрос Curl завершит работу.

В моем случае это были настройки прокси-сервера на моей локальной виртуальной машине. Запрос отправлялся на прокси, который не знал о сервере. Пропуском прокси решил проблему.

Когда я попробовал эти команды, я получил то же сообщение об ошибке «curl: (56) Ошибка приема: соединение было сброшено».

завиток завиток -L

Но это решило, когда с HTTPS

Curl -----> 302 документ переместил сообщение, которое ожидается. Curl -L http://google.comhttps://google.comhttps://google.comhttp://google.com

Другие вопросы по тегам