http - 在 .Net 中将 HTTP 2 与 HttpClient 结合使用

标签 http asp.net-core .net-core dotnet-httpclient http2

我正在尝试通过 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 环境变量设置为 0false

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

只要确保在更改目标运行时时彻底清理项目 - 删除 binobj 所有目标文件,或者您可能最终会像我一样运行错误的运行时。

在 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/

相关文章:

linux - 如何实现 HTTP API 守护进程

c# - 多个服务器在 HANGFIRE 中生成错误 500

c# - 从证书库导入的 X509 证书没有私钥

asp.net-core - 将 .net core 3.1 更新到 .net core 6 时出现 DevOps 管道 CI 错误

c# - 是否可以在 ASP.NET Core MVC 应用程序中运行 Blazor 客户端页面?

c# - 查找 Azure Blob 存储中所有带前缀的 Blob

使用http时angular 6未定义函数

ruby-on-rails - 如何使用 Ruby on Rails 3 检查 HTTP 请求的字段 'Content-Length '?

Http 协议(protocol)机制和对象

sql-server - 升级 Microsoft.EntityFrameworkCore.SqlServer 版本时出错