我正在尝试通过 HTTP 2.0 请求数据。我正在使用 .Net Core 2.2 中的 HttpClient。我在 Windows 10 上,但在生产环境中将在 Linux 上运行。问题是响应中的版本似乎总是“1.1”。我做错了什么?
using (var client = new HttpClient())
{
using (var request = new HttpRequestMessage(new HttpMethod("GET"),
"https://duckduckgo.com/"
))
{
request.Version = new Version(2, 0);
var response = await client.SendAsync(request);
Console.WriteLine(response.Version);
}
}
最佳答案
更新 - .NET Core 3.0
.NET Core 3.0 现在 supports HTTP/2 .以下代码将打印 2.0
:
var client = new HttpClient();
var req = new HttpRequestMessage(HttpMethod.Get, "https://http2.akamai.com/demo"){
Version = new Version(2, 0)
};
var x = await client.SendAsync(req);
var version = x.Version;
Console.WriteLine(version);
原始答案
你 can't use HTTP/2 with HttpClient in .NET Core 2.1 or 2.2 ,即使您在请求中明确设置了版本。您必须显式配置 .NET Core 以使用 .NET Core 2.0 附带的旧 HttpClientHandler 实例,方法是通过以下方式设置 App Context 开关:
AppContext.SetSwitch("System.Net.Http.UseSocketsHttpHandler", false);
或者通过将 DOTNET_SYSTEM_NET_HTTP_USESOCKETSHTTPHANDLER
环境变量设置为 0
或 false
。
this Github issue 中的讨论表明 .NET Core 3.0 计划支持 HTTP/2。 Microsoft Connect 2018 上发布的 3.0 Preview 1 尚不支持 HTTP/2。
HttpClientHandler 使用到 .NET Core 2.0 支持 HTTP/2。以下代码将在以 Core 2.0 为目标的项目中返回 2.0
:
var client = new HttpClient();
var req = new HttpRequestMessage(HttpMethod.Get, "https://http2.akamai.com/demo")
{
Version = new Version(2, 0)
};
var x = await client.SendAsync(req);
var version = x.Version;
Console.WriteLine(version);
只要确保在更改目标运行时时彻底清理项目 - 删除 bin
、obj
和 所有目标文件,或者您可能最终会像我一样运行错误的运行时。
在 2.1 中,默认添加了一个新的、更快的 SocketsHttpClientHandler。新的处理程序尚不支持 HTTP/2。相同的代码将返回 1.1
作为协议(protocol)版本。
如果在创建 HttpClient 之前设置了应用上下文切换,则使用 HTTP/2。此代码将返回 2.0
。有趣的是,无需指定 HTTP 版本。当 HTTP/2 可用时,将协商实际的协议(protocol)版本。 Akamai URL 和 https://www.google.com
都将使用 HTTP/2,即使未指定版本也是如此:
AppContext.SetSwitch("System.Net.Http.UseSocketsHttpHandler", false);
var client = new HttpClient();
var req = new HttpRequestMessage(HttpMethod.Get, "https://http2.akamai.com/demo");
var x = await client.SendAsync(req);
var version = x.Version;
switch和环境变量在官方公告中有说明.NET Core 2.1 SDK Preview 2 :
Sockets Performance and SocketsHttpHandler
We made major improvements to sockets in .NET Core 2.1. Sockets are the basis of both outgoing and incoming networking communication. The higher-level networking APIs in .NET Core 2.1, including HttpClient and Kestrel, are now based on .NET sockets. In earlier versions, these higher-level APIs were based on native networking implementations.
...
You can use one of the following mechanisms to configure a process to use the older HttpClientHandler:
From code, use the AppContext class:
AppContext.SetSwitch("System.Net.Http.UseSocketsHttpHandler", false);
The AppContext switch can also be set by config file.
The same can be achieved via the environment variable DOTNET_SYSTEM_NET_HTTP_USESOCKETSHTTPHANDLER. To opt out, set the value to either false or 0.
关于http - 在 .Net 中将 HTTP 2 与 HttpClient 结合使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53764083/