HttpClient 类
定义
重要
一些信息与预发行产品相关,相应产品在发行之前可能会进行重大修改。 对于此处提供的信息,Microsoft 不作任何明示或暗示的担保。
提供一个类,用于发送 HTTP 请求并从 URI 标识的资源接收 HTTP 响应。
public ref class HttpClient : System::Net::Http::HttpMessageInvoker
public class HttpClient : System.Net.Http.HttpMessageInvoker
type HttpClient = class
inherit HttpMessageInvoker
Public Class HttpClient
Inherits HttpMessageInvoker
- 继承
示例
// HttpClient is intended to be instantiated once per application, rather than per-use. See Remarks.
static readonly HttpClient client = new HttpClient();
static async Task Main()
{
// Call asynchronous network methods in a try/catch block to handle exceptions.
try
{
HttpResponseMessage response = await client.GetAsync("http://www.contoso.com/");
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
// Above three lines can be replaced with new helper method below
// string responseBody = await client.GetStringAsync(uri);
Console.WriteLine(responseBody);
}
catch(HttpRequestException e)
{
Console.WriteLine("\nException Caught!");
Console.WriteLine("Message :{0} ",e.Message);
}
}
open System.Net.Http
// HttpClient is intended to be instantiated once per application, rather than per-use. See Remarks.
let client = new HttpClient()
let main =
task {
// Call asynchronous network methods in a try/catch block to handle exceptions.
try
let! response = client.GetAsync "http://www.contoso.com/"
response.EnsureSuccessStatusCode() |> ignore
let! responseBody = response.Content.ReadAsStringAsync()
// Above three lines can be replaced with new helper method below
// let! responseBody = client.GetStringAsync uri
printfn $"{responseBody}"
with
| :? HttpRequestException as e ->
printfn "\nException Caught!"
printfn $"Message :{e.Message} "
}
main.Wait()
' HttpClient is intended to be instantiated once per application, rather than per-use. See Remarks.
Shared ReadOnly client As HttpClient = New HttpClient()
Private Shared Async Function Main() As Task
' Call asynchronous network methods in a try/catch block to handle exceptions.
Try
Dim response As HttpResponseMessage = Await client.GetAsync("http://www.contoso.com/")
response.EnsureSuccessStatusCode()
Dim responseBody As String = Await response.Content.ReadAsStringAsync()
' Above three lines can be replaced with new helper method below
' Dim responseBody As String = Await client.GetStringAsync(uri)
Console.WriteLine(responseBody)
Catch e As HttpRequestException
Console.WriteLine(Environment.NewLine & "Exception Caught!")
Console.WriteLine("Message :{0} ", e.Message)
End Try
End Function
前面的代码示例使用 async Task Main()
入口点。 此功能需要 C# 7.1 或更高版本。
注解
类 HttpClient 实例充当发送 HTTP 请求的会话。 HttpClient实例是应用于该实例执行的所有请求的设置集合。 此外,每个 HttpClient 实例都使用自己的连接池,将请求与其他实例执行 HttpClient 的请求隔离开来。
实例化
HttpClient 旨在实例化一次,并在应用程序的整个生命周期内重复使用。 在 .NET Core 和 .NET 5+ 中,HttpClient 在处理程序实例内池连接,并在多个请求之间重复使用连接。 如果为每个请求实例化 HttpClient 类,则大量负载下可用的套接字数将耗尽。 这种耗尽将导致 SocketException 错误。
可以通过将“处理程序”(如 HttpClientHandler (或 SocketsHttpHandler .NET Core 2.1 或更高版本) )作为构造函数的一部分来配置其他选项。 提交请求后,无法更改处理程序上的连接属性,因此,如果需要更改连接属性,则创建新的 HttpClient 实例的原因之一。 如果不同的请求需要不同的设置,则这也可能导致应用程序具有多个 HttpClient 实例,其中每个实例都已正确配置,然后在相关客户端上发出请求。
HttpClient 仅在创建连接时解析 DNS 条目。 它不会跟踪 DNS 服务器指定的任何生存时间 (TTL) 持续时间。 如果 DNS 条目定期更改,这在某些容器方案中可能发生,则客户端不会尊重这些更新。 若要解决此问题,可以通过设置 SocketsHttpHandler.PooledConnectionLifetime 属性来限制连接的生存期,以便在替换连接时需要 DNS 查找。
public class GoodController : ApiController
{
private static readonly HttpClient httpClient;
static GoodController()
{
var socketsHandler = new SocketsHttpHandler
{
PooledConnectionLifetime = TimeSpan.FromMinutes(2)
};
httpClient = new HttpClient(socketsHandler);
}
}
作为仅创建一个 HttpClient 实例的替代方法,还可以用于 IHttpClientFactory 管理 HttpClient 实例。 有关详细信息,请参阅 使用 HttpClient 的准则。
派生
它还 HttpClient 充当更具体的 HTTP 客户端的基类。 例如,FacebookHttpClient 提供了特定于 Facebook Web 服务的其他方法 (,例如 GetFriends
方法) 。 派生类不应重写类上的虚拟方法。 请改用接受 HttpMessageHandler 的构造函数重载来配置任何预请求或请求后处理。
传输
HttpClient这是一个高级 API,用于包装其运行的每个平台上可用的较低级别功能。
在每个平台上, HttpClient 尝试使用最佳可用传输:
主机/运行时 | 后端 |
---|---|
Windows/.NET Framework | HttpWebRequest |
Windows/Mono | HttpWebRequest |
Windows/UWP | 支持 HTTP 2.0 的 Windows 本机 WinHttpHandler () |
Windows/.NET Core 1.0-2.0 | 支持 HTTP 2.0 的 Windows 本机 WinHttpHandler () |
Android/Xamarin | 在生成时选择。 HttpWebRequest可以使用或配置为使用 Android 的本机HttpURLConnection |
iOS, tvOS, watchOS/Xamarin | 在生成时选择。 HttpWebRequest可以使用或配置为使用支持 Apple (NSUrlSession HTTP 2.0 的) |
macOS/Xamarin | 在生成时选择。 HttpWebRequest可以使用或配置为使用支持 Apple (NSUrlSession HTTP 2.0 的) |
macOS/Mono | HttpWebRequest |
macOS/.NET Core 1.0-2.0 | libcurl 基于 HTTP 传输 (支持 HTTP 2.0) |
Linux/Mono | HttpWebRequest |
Linux/.NET Core 1.0-2.0 | libcurl 基于 HTTP 传输 (支持 HTTP 2.0) |
.NET Core 2.1 及更高版本 | System.Net.Http.SocketsHttpHandler |
用户还可以通过调用HttpClient采用的HttpMessageHandler构造函数来HttpClient配置特定传输。
.NET Framework & Mono
默认情况下,在 .NET Framework 和 Mono 上,HttpWebRequest用于向服务器发送请求。 可以通过使用参数在构造函数重载 HttpMessageHandler 之一中指定不同的处理程序来修改此行为。 如果需要身份验证或缓存等功能,则可以用于 WebRequestHandler 配置设置,实例可以传递给构造函数。 返回的处理程序可以传递给具有 HttpMessageHandler 参数的构造函数重载。
.NET Core
从 .NET Core 2.1 开始, System.Net.Http.SocketsHttpHandler 该类而不是 HttpClientHandler 提供更高级别的 HTTP 网络类(例如 HttpClient)使用的实现。 使用 SocketsHttpHandler 提供了许多优点:
- 对照以前的实现,可以看到显著的性能改进。
- 消除平台依赖项,这简化了部署和服务。 例如,
libcurl
不再依赖于适用于 macOS 的 .NET Core 和适用于 Linux 的 .NET Core。 - 在所有 .NET 平台上的一致行为。
如果不需要此更改,可以在 Windows 上通过引用其 NuGet 包并将其手动传递给 HttpClient 的构造函数来WinHttpHandler继续使用。
使用运行时配置选项配置行为
某些方面 HttpClient的行为可通过 运行时配置选项进行自定义。 但是,这些开关的行为因 .NET 版本而异。 例如,在 .NET Core 2.1 - 3.1 中,可以配置默认是否 SocketsHttpHandler 使用,但从 .NET 5.0 开始,该选项不再可用。
连接池
HttpClient 尽可能池 HTTP 连接,并将它们用于多个请求。 这可以具有显著的性能优势,尤其是对于 HTTPS 请求,因为连接握手仅完成一次。
连接池属性可以在构造期间配置 HttpClientHandler 或 SocketsHttpHandler 传入,包括 MaxConnectionsPerServer, PooledConnectionIdleTimeout和 PooledConnectionLifetime。
释放 HttpClient 实例会关闭打开的连接并取消任何挂起的请求。
备注
如果将 HTTP/1.1 请求并发发送到同一服务器,则可以创建新连接。 即使重复使用 HttpClient
实例,如果请求速率很高,或者存在任何防火墙限制,由于默认 TCP 清理计时器,可能会耗尽可用套接字。 若要限制并发连接数,可以设置属性 MaxConnectionsPerServer
。 默认情况下,并发 HTTP/1.1 连接数不受限制。
缓冲和请求生存期
默认情况下,HttpClient 方法 (,) GetStreamAsync 缓冲来自服务器的响应,在返回异步结果之前将所有响应正文读取到内存中。 这些请求将继续,直到发生以下情况之一:
- 成功 Task<TResult> 并返回结果。
- 达到此 Timeout 情况时 Task<TResult> ,将取消该操作。
- CancellationToken将触发传递给某些方法重载。
- 调用 CancelPendingRequests()。
- HttpClient 已释放。
可以使用某些方法重载上可用的参数,根据 HttpCompletionOption 每个请求更改缓冲行为。 此参数可用于指定在仅读取响应标头后或读取和缓冲响应内容后是否 Task<TResult> 应被视为完成。
如果命名空间中使用System.Net.Http和相关类的应用HttpClient打算下载大量数据, (50 兆字节或更多) ,则应用应流式传输这些下载,而不使用默认缓冲。 如果使用默认缓冲,则客户端内存使用率将非常大,这可能会导致性能大幅降低。
线程安全
以下方法是线程安全的:
- CancelPendingRequests
- DeleteAsync
- GetAsync
- GetByteArrayAsync
- GetStreamAsync
- GetStringAsync
- PostAsync
- PutAsync
- SendAsync
代理
默认情况下,HttpClient 根据平台从环境变量或用户/系统设置读取代理配置。 可以通过按优先级顺序传递 WebProxy 或 IWebProxy 传递给此行为:
- Proxy HttpClientHandler 在 HttpClient 构造过程中传入的属性
- DefaultProxy静态属性 (会影响所有实例)
可以使用 UseProxy. Windows 用户的默认配置是尝试并使用网络发现来检测代理,这可能很慢。 对于已知不需要代理的高吞吐量应用程序,应禁用代理。
仅应在使用 HttpClient 发出第一个请求之前更改 (代理设置,如 Credentials) 。 首次使用 HttpClient 后所做的更改可能不会反映在后续请求中。
超时
可用于 Timeout 为来自 HttpClient 实例的所有 HTTP 请求设置默认超时。 超时仅适用于导致启动请求/响应的 xxxAsync 方法。 如果达到超时,则会 Task<TResult> 取消该请求。
如果在构造 HttpClient 对象时传入实例, SocketsHttpHandler 可以设置一些额外的超时:
属性 | 说明 |
---|---|
ConnectTimeout | 指定在请求需要创建新的 TCP 连接时使用的超时。 如果发生超时,将取消请求 Task<TResult> 。 |
PooledConnectionLifetime | 指定要用于连接池中每个连接的超时值。 如果连接处于空闲状态,则连接会立即关闭;否则,连接在当前请求结束时关闭。 |
PooledConnectionIdleTimeout | 如果连接池中的连接长时间处于空闲状态,则连接将关闭。 |
Expect100ContinueTimeout | 如果请求具有“预期:100-continue”标头,它会延迟发送内容,直到超时或收到“100-continue”响应为止。 |
HttpClient 仅在创建连接时解析 DNS 条目。 它不会跟踪 DNS 服务器指定的任何生存时间 (TTL) 持续时间。 如果 DNS 条目定期更改(在某些情况下可能发生),则可以使用 PooledConnectionLifetime 限制连接的生存期,以便在替换连接时需要 DNS 查找。
构造函数
HttpClient() |
使用释放此实例时释放的 HttpClientHandler 初始化 HttpClient 类的新实例。 |
HttpClient(HttpMessageHandler) |
使用指定的处理程序初始化 HttpClient 类的新实例。 处理程序在释放此实例时被释放。 |
HttpClient(HttpMessageHandler, Boolean) |
使用提供的处理程序初始化 HttpClient 类的新实例,并指定在释放此实例时是否应释放该处理程序。 |
属性
BaseAddress |
获取或设置发送请求时使用的 Internet 资源的统一资源标识符 (URI) 的基址。 |
DefaultProxy |
获取或设置全局 HTTP 代理。 |
DefaultRequestHeaders |
获取与每个请求一起发送的标题。 |
DefaultRequestVersion |
获取或设置对此 HttpClient 实例发出的后续请求使用的默认 HTTP 版本。 |
DefaultVersionPolicy |
获取或设置便捷方法中隐式创建的请求的默认版本策略,例如 GetAsync(String) 和 PostAsync(String, HttpContent)。 |
MaxResponseContentBufferSize |
获取或设置读取响应内容时要缓冲的最大字节数。 |
Timeout |
获取或设置请求超时前等待的时间跨度。 |