Что делает этот HTTPS WebRequest тайм-аут, хотя он работает в браузере? - PullRequest
19 голосов
/ 13 апреля 2011

Вот мой запрос:

var request = (HttpWebRequest) WebRequest.Create("https://mtgox.com/");
request.CookieContainer = new CookieContainer();
request.AllowAutoRedirect = false;
request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
request.Headers[HttpRequestHeader.AcceptEncoding] = "gzip, deflate";
request.Headers[HttpRequestHeader.AcceptLanguage] = "en-gb,en;q=0.5";
request.Headers[HttpRequestHeader.AcceptCharset] = "ISO-8859-1,utf-8;q=0.7,*;q=0.7";
request.Timeout = 5000;
request.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:2.0) Gecko/20100101 Firefox/4.0";
request.Method = "GET";

request.GetResponse();

Заголовки были скопированы из Firefox с использованием HttpFox.Я использовал Fiddler2, чтобы убедиться, что по крайней мере для HTTP-запросов заголовки полностью совпадают между запросами Firefox и моими запросами.

Однако при выполнении запроса к этому конкретному веб-сайту с использованием HTTPSзапрос просто истекает.Он работает для других веб-сайтов.

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

Это просто действительно глючный сайт?Какая часть из вышеперечисленного выдает меня за то, что я не Firefox?

Ответы [ 6 ]

43 голосов
/ 15 апреля 2011

Используя Microsoft Network Monitor, я обнаружил, что HttpWebRequest застрянет на этапе, когда он должен отправить обратно клиентский обмен ключами. Это просто не так. Сервер должным образом ждал этого, но он так и не пришел.

Что исправило: HttpWebRequest использовал SSL3 вместо TLS (даже если TLS должен автоматически превращаться в SSL3 при необходимости):

ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;

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

Одна вещь, которая отличалась от перехватов: вариант TLS имел запись "Alert" в ответе Server Hello , которая отсутствует на обмене SSL3, а также на всех обменах TLS, которые фактически работали , Любопытно, что такое же предупреждение присутствует при захвате Firefox, успешно выполняющем запрос.

Наконец, кажется, что во время первой публикации этого вопроса был временный сбой OCSP, который с тех пор был решен. Это добавляет беспорядка, но не является основной проблемой.

11 голосов
/ 15 сентября 2013

Типичная причина ошибок тайм-аута при вызовах HttpWebRequest / HttpWebReponse - «не закрытие объекта / потока ответа», которые поддерживают активные соединения.Вы должны просто закрыть объект Stream или HttpWebResponse после чтения содержимого потока.Предел подключения по умолчанию равен 2.

HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse();
Stream stream = webResponse.GetResponseStream();
string responseString = ((TextReader)new StreamReader(stream)).ReadToEnd();
webResponse.Close();

В качестве альтернативы, если вы реализовали свою логику в веб-сервисе, который будет одновременно вызываться многими пользователями, вы можете рассмотреть возможность увеличения ограничения подключения в HttpWebRequestобъект.

HttpWebRequest webRequest = (HttpWebRequest)HttpWebRequest.Create(url);    
webRequest.ServicePoint.ConnectionLimit = 20;
9 голосов
/ 15 октября 2011

.NET Framework в Windows 7 реализует расширение TLS: указание имени сервера (RFC4366). Согласно вашему сообщению Что означает это предупреждение TLS сервер отвечает «Нераспознанное имя». Не уверен, почему сообщается, что соединение истекло, потому что это действительно не так. Трассировки вашей сети должны показать, что клиент инициирует разрыв соединения после этого [FIN, ACK]. Понижение до SSL3 позволяет избежать вызова SNI.

К сведению: та же платформа .NET в Windows XP не использует расширение индикации имени сервера TLS. Ваша программа там будет работать ....

В моем случае я проследил возникновение этого до отсутствующей директивы ServerName в Apache. Добавление ServerName к конфигурации SSL решило эту проблему, поскольку теперь веб-сервер больше не знает своего имени.

4 голосов
/ 26 июля 2013

Недавно узнал об этой же проблеме и хотел посмотреть, исправила ли Microsoft эту проблему в более новых версиях .net. Это код, который я тестировал (домен удален для конфиденциальности):

HttpWebRequest request =
    (HttpWebRequest)WebRequest.Create("https://www.xxSomeDomainNamexx.com/");
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
StreamReader reader = new StreamReader(response.GetResponseStream());
Console.WriteLine(reader.ReadToEnd());

Скомпилировано это с версиями .net 2.0, 3.0 и 3.5, и, похоже, все они демонстрируют точно такое же поведение, как все здесь обсуждали. Затем я попытался скомпилировать против 4.0 и 4.5 и получил правильные ответы в обоих местах.

Исходя из этого, похоже, что Microsoft, скорее всего, исправила эту проблему в более новых версиях .net. Для потомков я также протестировал изменение SecurityProtocol, предложенное enverpex, и оно отлично работало на 2.0, 3.0 и 3.5.

3 голосов
/ 23 сентября 2016

У меня была та же проблема тайм-аута с запросами https, и ни один из ответов мне не помог.Только сейчас я нашел решение, которое решило проблему для меня.Обратите внимание, что это работает только с .net Framework 4.5 или выше.

System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
var response = WebRequest.Create("https://yoursecurewebservice").GetResponse();
var body = new StreamReader(response.GetResponseStream()).ReadToEnd();
Console.WriteLine(body);
2 голосов
/ 13 апреля 2011

Скорее всего, клиент HTTPS не может проверить цепочку сертификатов, представленную этим сервером, например, из-за отсутствия корневого сертификата или недоступного респондента OCSP.Т.е. в браузере и в используемом вами HTTPS-клиенте может быть настроено что-то другое.

В качестве одного из вариантов вы можете воспользоваться пробной версией наших HTTPBlackbox компонентов и попробовать подключиться с помощью TElHTTPSClient.Он предоставит вам подробную информацию об ошибке (в случае ошибки), чтобы вы могли определить, что не так с HttpWebRequest.

...