在某些主机上,使用System.Net.Http.HttpClient时,连接保持活动状态不起作用。

7
我正在使用.NET的System.Net.Http.HttpClient实验Heroku API。特别是,我想让keep-alive起作用,这样我就可以使用一个TCP连接发送多个HTTP请求,并且只进行一次SSL握手,而不是针对每个请求建立带有SSL握手的TCP连接。
我正在测试https://api.heroku.com/status,它提供了一个很好的HTTP 200,并使用Wireshark监视TCP流量。
Google Chrome、ApacheBench(带-k标志)和curl似乎都能保持TCP连接开放并发送多个请求。HttpClient则不然。我还使用HttpClient对其他主机进行了测试(例如https://google.com/),在那里我只看到了一个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

这里发生了什么事,有什么建议吗?


Fiddler显示什么?如果它们协商HTTP 1.0,则需要显式的Keep-Alive头。 - Stephen Cleary
@StephenCleary 谷歌浏览器显示HTTP/1.1。 - friism
我是指在 HttpClient 和 Heroku 之间。 - Stephen Cleary
@StephenCleary 当调试和检查东西时,我从HttpClient获取的HttpResponseMessage显示Version: 1.1,所以我认为这是可以的。我还使用Fiddler2进行了测试 - 它是HTTP 1.1,并且Connection: keep-alive已经正确发送。 - friism
2个回答

7

0
一些代理服务器在进行身份验证时会忽略保持连接。如果我没记错的话,这是当代理服务器使用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;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接