连接keep-alive在某些主机上无法与System.Net.Http.HttpClient一起使用

时间:2013-07-27 05:52:31

标签: .net http ssl tcp dotnet-httpclient

我正在使用.NET System.Net.Http.HttpClient试验Heroku API。特别是,我希望keep-alive能够工作,以便我可以使用一个TCP连接发送许多HTTP请求,并且只进行一次SSL握手,而不是使用每次请求的SSL握手设置TCP连接。

我正在测试https://api.heroku.com/status,它提供了一个不错的HTTP 200,并使用Wireshark来监控TCP流量。

谷歌浏览器,ApacheBench(带有-k标志)和curl似乎都能够保持TCP连接打开并发送多个请求。 HttpClient,不是那么多。我还针对其他主机(例如https://google.com/)测试了HttpClient,在那里我只看到一个SSL握手/ TCP设置。所以看起来这是HttpClient和Heroku API之间的不良交互。

以下是我正在测试的代码:

private static async void TestUrl(string url)
{
    using (var client = GetClient())
    {
        await client.GetAsync(url);
        await client.GetAsync(url);
        await client.GetAsync(url);
        await client.GetAsync(url);
    }
}

private static HttpClient GetClient()
{
    var requestHandler = new HttpClientHandler
    {
        UseCookies = false,
        AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip,
    };

    return new HttpClient(requestHandler);
}

我还附上了一个Wireshark屏幕截图,显示了HttpClient在接收到数据后立即决定重置(RST)连接。

Wireshark screenshot

对于这里发生了什么有任何建议吗?

2 个答案:

答案 0 :(得分:6)

使用 WebRequestHandler 类而不是 HttpClientHandler 并将属性HttpWebRequest.UnsafeAuthenticatedConnectionSharing 设置为True。

答案 1 :(得分:0)

某些代理服务器在进行身份验证时会忽略keep-alive。如果我没记错的话,那就是代理服务器使用NTLM身份验证的时候。

过去,我必须添加一个部分类来“帮助”一些Web服务代理类。

我用

覆盖了GetWebRequest(Uri uri)方法
System.Net.HttpWebRequest webRequest = 
        (System.Net.HttpWebRequest)base.GetWebRequest(uri);
webRequest.ProtocolVersion = HttpVersion.Veraion10;  // I know this is strange, but it works
webRequest.ServicePoint.Expect100Continue = false;  // This is where the magic lives
return webRequest;