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
{
using 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
use! 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
Using 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)
End Using
Catch e As HttpRequestException
Console.WriteLine(Environment.NewLine & "Exception Caught!")
Console.WriteLine("Message :{0} ", e.Message)
End Try
End Function
備註
類別 HttpClient 實例可作為傳送 HTTP 要求的會話。 HttpClient實例是套用至該實例所執行之所有要求的設定集合。 此外,每個實例都會HttpClient使用自己的連接池,將其要求與其他實例HttpClient執行的要求隔離開來。
Instancing
HttpClient 旨在具現化一次,並在整個應用程式的生命週期中重複使用。 在 .NET Core 和 .NET 5+ 中,HttpClient 會將連線放入處理程序實例的池中,並在多個請求中重複使用該連線。 如果你為每個請求實例化一個 HttpClient 類別,在重負載下可用的 socket 數量將會被耗盡。 此耗盡會導致 SocketException 錯誤。
您可以透過傳入「處理程式」來配置其他選項,例如 HttpClientHandler (或在 .NET Core 2.1 或更高版本中使用 SocketsHttpHandler),作為建構函式的一部分。 處理器上的連線屬性一旦提交請求後就無法更改,因此建立新 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 用戶端的基類。 例如,一個提供 Facebook 網路服務額外方法的 FacebookHttpClient(例如,一個 GetFriends 方法)。 衍生類別不應覆蓋該類別中的虛擬方法。 請改用接受 HttpMessageHandler 的建構函式多載來設定任何預先要求或要求后處理。
Transports
HttpClient是一個高階 API,會包裝其執行所在每個平臺上可用的較低層級功能。
在每個平臺上, HttpClient 嘗試使用最佳的可用傳輸:
| 主機/運行時間 | 後端 |
|---|---|
| Windows/.NET 框架 | HttpWebRequest |
| Windows/Mono | HttpWebRequest |
| Windows/UWP | Windows 原生 WinHttpHandler (HTTP 2.0 支援) |
| Windows/.NET 核心 1.0-2.0 | Windows 原生 WinHttpHandler (HTTP 2.0 支援) |
| macOS/Mono | HttpWebRequest |
| macOS/.NET 核心 1.0-2.0 |
libcurl型 HTTP 傳輸 (支援 HTTP 2.0) |
| Linux/Mono | HttpWebRequest |
| Linux/.NET 核心 1.0-2.0 |
libcurl型 HTTP 傳輸 (支援 HTTP 2.0) |
| .NET Core 2.1 和更新版本 | System.Net.Http.SocketsHttpHandler |
使用者也可以通過叫用採用 HttpClient的 HttpClient建構函式來配置 HttpMessageHandler 的特定傳輸。
.NET Framework 和 Mono
根據預設, HttpWebRequest .NET Framework 和 Mono 會用來將要求傳送至伺服器。 要修改此行為,可在其中一個具有 HttpMessageHandler 參數的建構函式多載中指定不同的處理程式。 如果您需要驗證或快取等功能,您可以使用 WebRequestHandler 來設定設定,並將實例傳遞至建構函式。 傳回的處理程式可以傳遞至具有 HttpMessageHandler 參數的建構函式多載。
.NET 核心
從 .NET Core 2.1 開始,類別 System.Net.Http.SocketsHttpHandler 取代了 HttpClientHandler,提供較高層級 HTTP 網路類別所使用的實作,例如 HttpClient。 使用 SocketsHttpHandler 提供許多優點:
- 相較於先前的實作,效能大幅改善。
- 消除平臺相依性,可簡化部署和服務。 例如,
libcurl不再相依於macOS的 .NET Core 和適用於Linux的 .NET Core。 - 所有 .NET 平臺的一致行為。
如果這項變更不理想,您可以在 Windows 上繼續使用 WinHttpHandler ,方法是參考其 NuGet 套件 ,並手動將它傳遞至 HttpClient 的建構函式 。
使用執行時組態選項設定行為
某些方面 HttpClient的行為可透過 運行時間組態選項來自定義。 不過,這些開關的行為在不同的 .NET 版本中有所不同。 例如,在 .NET Core 2.1 - 3.1 中,您可以設定是否 SocketsHttpHandler 預設使用 ,但從 .NET 5 開始,就無法再使用該選項。
連線池化
HttpClient 盡可能池化 HTTP 連線,並用於多個請求。 這可以帶來顯著的效能上的提升,尤其對於 HTTPS 請求來說,因為連線的握手只需進行一次。
連接集區屬性可以在建構過程中通過HttpClientHandler或SocketsHttpHandler來配置,包括MaxConnectionsPerServer、PooledConnectionIdleTimeout和PooledConnectionLifetime。
丟棄 HttpClient 實例會關閉所有未完成的連線並取消所有待處理的請求。
Note
如果您同時將 HTTP/1.1 要求傳送至相同的伺服器,則可以建立新的連線。 即使您重複使用 HttpClient 實例,但如果請求率很高或存在任何防火牆限制,由於預設的 TCP 清理計時器,這可能會耗盡可用的套接字。 若要限制並行連線數目,您可以設定 MaxConnectionsPerServer 屬性。 根據預設,並行 HTTP/1.1 連線的數目不受限制。
緩衝處理和請求壽命
預設情況下, HttpClient 方法(除了 GetStreamAsync)會緩衝伺服器的回應,將所有回應內容讀入記憶體,然後回傳非同步結果。 這些請求會持續進行,直到發生下列其中一項:
- Task<TResult> 成功並傳回結果。
- 達到 Timeout 的情況下,Task<TResult> 將會被取消。
- CancellationToken 將被觸發並可傳遞至某些方法的多載。
- 呼叫 CancelPendingRequests()。
- HttpClient 已處置。
您可以使用某些方法重載中可用的HttpCompletionOption參數,根據每個請求變更緩衝行為。 這個參數可以用來指定僅讀取回應標頭後,或在讀取和緩衝回應內容後,是否應將 Task<TResult> 視為完成。
如果您的應用程式在 HttpClient 命名空間中使用 System.Net.Http 和相關類別想要下載大量數據(50 MB 以上),則應用程式應該串流這些下載,而不使用預設的緩衝處理。 如果您使用默認緩衝處理,則用戶端記憶體使用量會變得非常大,可能會導致大幅降低效能。
螺紋安全
下列方法是執行緒安全:
- CancelPendingRequests
- DeleteAsync
- GetAsync
- GetByteArrayAsync
- GetStreamAsync
- GetStringAsync
- PostAsync
- PutAsync
- SendAsync
Proxy
預設情況下,HttpClient 根據平台不同,從環境變數或使用者/系統設定中讀取代理配置。 您可以通過依優先順序傳遞WebProxy或IWebProxy來變更此行為。
-
Proxy屬性在
HttpClientHandler建構期間被HttpClient傳入 - DefaultProxy靜態屬性 (影響所有實例)
您可以關閉代理 UseProxy。 Windows 使用者的預設組態是藉由網路探索來偵測 Proxy,這可能會很慢。 對於已知不需要代理伺服器的高輸送量應用程式,您應該停用代理伺服器。
代理設定(例如 Credentials)應該僅在使用 HttpClient 發出第一次請求前更改。 首次使用後 HttpClient 所做的變更,可能不會反映在後續的請求中。
Timeouts
你可以使用 Timeout 設定 HttpClient 實例所有 HTTP 請求的預設逾時。 逾時僅適用於導致起始要求/回應的 xxxAsync 方法。 如果達到逾時,則會取消該請求的Task<TResult>。
如果您在構造SocketsHttpHandler對象時傳遞一個HttpClient實例,可以設定一些額外的超時時間:
| Property | Description |
|---|---|
| ConnectTimeout | 指定用於當要求需要建立新的 TCP 連線時的逾時設定。 如果發生逾時,則會取消請求 Task<TResult> 。 |
| PooledConnectionLifetime | 指定連接池中每個連線的超時設定。 如果連線處於閑置狀態,則會立即關閉連線;否則,連接會在目前要求的結尾關閉。 |
| PooledConnectionIdleTimeout | 如果連線集區中的連線長時間閑置,連線就會關閉。 |
| Expect100ContinueTimeout | 如果要求有「預期:100-continue」標頭,則會延遲傳送內容直到逾時或收到「100-continue」回應為止。 |
HttpClient 只有在連線建立時才解析 DNS 條目。 它不會追蹤 DNS 伺服器所指定的任何存留時間 (TTL) 長度。 如果 DNS 條目經常變更,這可能發生在某些容器場景中,您可以使用 PooledConnectionLifetime 來限制連線的存留期,以便在取代連線時需要進行 DNS 查詢。
建構函式
| 名稱 | Description |
|---|---|
| HttpClient() |
使用HttpClient當該實例被處置時,初始化類別的新實例HttpClientHandler。 |
| HttpClient(HttpMessageHandler, Boolean) |
初始化該類別的新實例 HttpClient ,並指定該處理器在處理時是否應被丟棄。 |
| HttpClient(HttpMessageHandler) |
初始化一個新的類別實例 HttpClient ,使用指定的處理器。 當該實例被處理時,處理者即被處置。 |
屬性
| 名稱 | Description |
|---|---|
| BaseAddress |
取得或設定用於發送請求時所使用的網際網路資源的統一資源識別碼(URI)的基底位址。 |
| DefaultProxy |
取得或設定全域 HTTP Proxy。 |
| DefaultRequestHeaders |
它會取得每個請求都應該傳送的標頭。 |
| DefaultRequestVersion |
取得或設定此實例後續請求 HttpClient 所使用的預設 HTTP 版本。 |
| DefaultVersionPolicy |
取得或設定便利方法中隱含產生請求的預設版本政策, GetAsync(String)PostAsync(String, HttpContent)例如。 |
| MaxResponseContentBufferSize |
讀取回應內容時,會取得或設定最大緩衝位元組數。 |
| Timeout |
它會設定等待時間跨度,直到請求逾時。 |