是什么让这个HTTPS WebRequest即使在浏览器中运行也会超时?

时间:2011-04-13 18:33:49

标签: c# .net https httpwebrequest webrequest

这是我的要求:

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

使用HttpFox从Firefox复制标题。我使用Fiddler2验证至少对于HTTP请求,Firefox请求和我的请求之间的标题完全相同。

但是,在使用HTTPS执行此特定网站的请求时,请求会超时。它适用于其他网站。

我必须以不同的方式对Firefox执行,因为它始终适用于Firefox。但是,我无法使用Fiddler2调试它,因为每当Fiddler2转发这些请求时,它们也会超时,即使是由Firefox发起的。

这只是一个非常错误的网站吗?上面的哪一部分让我不喜欢Firefox?

6 个答案:

答案 0 :(得分:43)

使用Microsoft网络监视器,我发现HttpWebRequest会陷入应该发回客户端密钥交换的阶段。它根本没有。服务器正在等待它,但它从未到来。

是什么原因解决了强制HttpWebRequest使用SSL3而不是TLS(即使TLS应该在必要时自动变成SSL3):

ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;

为什么会这样,我想我永远不会知道 - 只是其中一个神秘的东西需要花费更多的时间来解决,而不是我认识的任何人愿意花费...

捕获的一个不同之处是:TLS变体had an "Alert" entry in the Server Hello response,它不存在于SSL3交换中,也来自实际工作的所有TLS交换。但奇怪的是,在成功执行请求的Firefox捕获中存在相同的警报。

最后,当我第一次发布这个问题时,似乎有一个临时的OCSP故障,此问题已经解决。这增加了混乱,但不是核心问题。

答案 1 :(得分:11)

HttpWebRequest / HttpWebReponse调用超时错误的典型原因是“没有关闭响应对象/流”,这会使连接保持活动状态。在读取流的内容后,您必须简单地关闭Stream对象或HttpWebResponse对象。默认连接限制为2。

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

或者,如果您在Web服务中实现了逻辑,该服务将被许多用户同时调用,那么您可能需要考虑增加HttpWebRequest对象中的连接限制。

HttpWebRequest webRequest = (HttpWebRequest)HttpWebRequest.Create(url);    
webRequest.ServicePoint.ConnectionLimit = 20;

答案 2 :(得分:9)

Windows 7上的.NET框架实现了TLS扩展:服务器名称指示(RFC4366)。根据您的帖子What does this TLS Alert mean,服务器正在响应“无法识别的名称”。不知道为什么连接被报告超时,因为它确实没有。您的网络跟踪应显示客户端在此[FIN,ACK]之后启动连接终止。降级到SSL3可以避免调用SNI。

仅供参考:Windows XP上的相同.NET框架不使用TLS服务器名称指示扩展。你的程序将在那里工作....

在我的例子中,我将这种情况的跟踪追溯到Apache中缺少的ServerName指令。将ServerName添加到SSL配置解决了它,因为现在Web服务器不再不知道它的名称。

答案 3 :(得分:4)

最近发现了同样的问题,并希望看看微软是否可以在较新的.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,并在两个地方都收到了正确的答案。

基于此,似乎微软很可能在较新的.net版本中解决了这个问题。对于后人,我还测试了enverpex建议的SecurityProtocol更改,它在2.0,3.0和3.5上运行良好。

答案 4 :(得分:3)

我有与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);

答案 5 :(得分:2)

很可能HTTPS客户端无法验证此服务器提供的证书链,例如由于缺少根证书或无法访问的OCSP响应程序。即您可以在浏览器和您使用的HTTPS客户端中配置不同的内容。

作为其中一个选项,您可以使用我们的HTTPBlackbox组件的试用版,并尝试使用TElHTTPSClient进行连接。它将为您提供详细的错误信息(如果出现错误),那么您将能够确定HttpWebRequest有什么问题。