System.Net.Http.HttpClient クラス

この記事では、この API のリファレンス ドキュメントへの補足的な解説を提供します。

クラス インスタンスは HttpClient 、HTTP 要求を送信するセッションとして機能します。 HttpClientインスタンスは、そのインスタンスによって実行されるすべての要求に適用される設定のコレクションです。 さらに、すべての HttpClient インスタンスは独自の接続プールを使用し、他 HttpClient のインスタンスによって実行される要求からその要求を分離します。

インスタンス化

HttpClient は、1 回インスタンス化され、アプリケーションの有効期間中に再利用されることを目的としています。 .NET Core と .NET 5 以降では、HttpClient はハンドラー インスタンス内の接続をプールし、複数の要求にわたって接続を再利用します。 すべての要求に対して HttpClient クラスをインスタンス化すると、大量の負荷で使用可能なソケットの数が使い果たされます。 この枯渇により、エラーが発生 SocketException します。

コンストラクターの一部として HttpClientHandler "ハンドラー" (または SocketsHttpHandler .NET Core 2.1 以降) を渡すことで、追加のオプションを構成できます。 要求が送信された後にハンドラーの接続プロパティを変更することはできません。そのため、新しい HttpClient インスタンスを作成する理由の 1 つは、接続プロパティを変更する必要がある場合です。 異なる要求で異なる設定が必要な場合は、アプリケーションに複数 HttpClient のインスタンスがあり、各インスタンスが適切に構成され、関連するクライアントで要求が発行される可能性もあります。

HttpClient は、接続の作成時にのみ DNS エントリを解決します。 DNS サーバーによって指定されている有効期限 (TTL) の期間は追跡されません。 一部のコンテナーのシナリオで発生する可能性があるような、DNS エントリが定期的に変更される場合、クライアントではこれらの更新は適用されません。 この問題を解決するには、接続が置き換えられるときに DNS 参照が必要になるように、SocketsHttpHandler.PooledConnectionLifetime プロパティを設定することで、接続の有効期間を制限できます。

public class GoodController : ApiController
{
    private static readonly HttpClient httpClient;

    static GoodController()
    {
        var socketsHandler = new SocketsHttpHandler
        {
            PooledConnectionLifetime = TimeSpan.FromMinutes(2)
        };

        httpClient = new HttpClient(socketsHandler);
    }
}

HttpClient インスタンスを 1 つだけ作成する代わりに、HttpClient インスタンスの管理にも使用 IHttpClientFactory できます。 詳細については、「HttpClient の使用に関するガイドライン」を参照してください。

派生

また、 HttpClient より具体的な HTTP クライアントの基底クラスとしても機能します。 たとえば、Facebook Web サービスに固有の追加メソッド (メソッドなど GetFriends ) を提供する FacebookHttpClient があります。 派生クラスは、クラスの仮想メソッドをオーバーライドしないでください。 代わりに、受け入れる HttpMessageHandler コンストラクター オーバーロードを使用して、要求前または要求後の処理を構成します。

トランスポート

これは HttpClient 、実行される各プラットフォームで使用できる下位レベルの機能をラップする高レベルの API です。

各プラットフォームで、 HttpClient 使用可能な最適なトランスポートの使用を試みます。

ホスト/ランタイム バックエンド
Windows/.NET Framework HttpWebRequest
Windows/Mono HttpWebRequest
Windows/UWP Windows ネイティブ WinHttpHandler (HTTP 2.0 対応)
Windows/.NET Core 1.0-2.0 Windows ネイティブ WinHttpHandler (HTTP 2.0 対応)
Android/Xamarin ビルド時に選択されます。 Android のネイティブを使用するように構成または使用 HttpWebRequest できます。 HttpURLConnection
iOS、tvOS、watchOS/Xamarin ビルド時に選択されます。 HttpWebRequest Apple (HTTP 2.0 対応) を使用するか、または Apple NSUrlSession を使用するように構成できます
macOS/Xamarin ビルド時に選択されます。 HttpWebRequest Apple (HTTP 2.0 対応) を使用するか、または Apple NSUrlSession を使用するように構成できます
macOS/Mono HttpWebRequest
macOS/.NET Core 1.0-2.0 libcurl-based HTTP トランスポート (HTTP 2.0 対応)
Linux/Mono HttpWebRequest
Linux/.NET Core 1.0-2.0 libcurl-based HTTP トランスポート (HTTP 2.0 対応)
.NET Core 2.1 以降 System.Net.Http.SocketsHttpHandler

また、ユーザーは、.を受け取るHttpMessageHandlerコンストラクターを呼び出すことによって、特定のHttpClientトランスポートHttpClientを構成することもできます。

.NET Framework & Mono

.NET Framework と Mono の既定では、 HttpWebRequest サーバーに要求を送信するために使用されます。 この動作は、パラメーターを使用してコンストラクターオーバーロードの 1 つで別のハンドラーを HttpMessageHandler 指定することで変更できます。 認証やキャッシュなどの機能が必要な場合は、設定を構成するために使用 WebRequestHandler でき、インスタンスをコンストラクターに渡すことができます。 返されたハンドラーは、パラメーターを持つコンストラクター オーバーロードに HttpMessageHandler 渡すことができます。

.NET Core

.NET Core 2.1 以降では、クラスの代わりに、System.Net.Http.SocketsHttpHandler次のようなHttpClient上位レベルの HttpClientHandler HTTP ネットワーク クラスで使用される実装が提供されます。 この使用 SocketsHttpHandler には、次のような多くの利点があります。

  • 以前の実装と比較して、パフォーマンスが大幅に向上しています。
  • プラットフォームの依存関係が排除され、デプロイとサービスが簡略化されます。 たとえば、 libcurl macOS 用の .NET Core と Linux 用の .NET Core への依存関係はなくなりました。
  • すべての .NET プラットフォームで一貫した動作。

この変更が望ましくない場合は、Windows で NuGet パッケージ参照し、それを HttpClient のコンストラクター手動で渡すことで、引き続き使用WinHttpHandlerできます。

ランタイム構成オプションを使用して動作を構成する

"動作" の特定のHttpClient側面は、ランタイム構成オプションを使用してカスタマイズできます。 ただし、これらのスイッチの動作は.NET バージョンによって異なります。 たとえば、.NET Core 2.1 から 3.1 では、既定で使用するかどうかを SocketsHttpHandler 構成できますが、そのオプションは .NET 5 以降では使用できなくなります。

接続のプール

HttpClient は可能な限り HTTP 接続をプールし、複数の要求に使用します。 接続ハンドシェイクは 1 回だけ実行されるため、特に HTTPS 要求の場合、パフォーマンスに大きなメリットがあります。

接続プールのプロパティは、構築中にHttpClientHandler構成することもSocketsHttpHandler、渡すことも可能です 。これにはMaxConnectionsPerServer、.PooledConnectionIdleTimeoutPooledConnectionLifetime..

HttpClient インスタンスを破棄すると、開いている接続が閉じられ、保留中の要求が取り消されます。

Note

HTTP/1.1 要求を同じサーバーに同時に送信する場合は、新しい接続を作成できます。 インスタンスをHttpClient再利用する場合でも、要求のレートが高い場合やファイアウォールの制限がある場合は、既定の TCP クリーンアップ タイマーが原因で使用可能なソケットが使い果たされる可能性があります。 同時接続の数を制限するには、プロパティを MaxConnectionsPerServer 設定します。 既定では、同時 HTTP/1.1 接続の数は無制限です。

バッファリングと要求の有効期間

既定では、HttpClient メソッド (除く GetStreamAsync) はサーバーからの応答をバッファー処理し、非同期結果を返す前にすべての応答本文をメモリに読み込みます。 これらの要求は、次のいずれかが発生するまで続行されます。

一部のメソッド オーバーロードで使用できるパラメーターを使用して、 HttpCompletionOption 要求ごとにバッファリング動作を変更できます。 この引数を使用して、応答ヘッダーのみを読み取った後、または応答の内容を読み取ってバッファー処理した後に、完了と見なす必要があるかどうかを Task<TResult> 指定できます。

名前空間内のSystem.Net.Httpクラスを使用し、関連するクラスを使用HttpClientするアプリが大量のデータ (50 メガバイト以上) をダウンロードする場合、アプリはそれらのダウンロードをストリーミングし、既定のバッファリングを使用しないようにする必要があります。 既定のバッファリングを使用すると、クライアントのメモリ使用量が非常に大きくなり、パフォーマンスが大幅に低下する可能性があります。

スレッド セーフ

次のメソッドはスレッド セーフです。

プロキシ

既定では、HttpClient は、プラットフォームに応じて、環境変数またはユーザー/システム設定からプロキシ構成を読み取ります。 この動作は、優先順位に従って渡すかIWebProxy、または次の順序で渡WebProxyすことによって変更できます。

  • Proxy HttpClient の構築中に渡された HttpClientHandler のプロパティ
  • DefaultProxy静的プロパティ (すべてのインスタンスに影響します)

を使用して UseProxyプロキシを無効にすることができます。 Windows ユーザーの既定の構成では、ネットワーク検出を使用してプロキシを検出しようとしますが、これは低速になる可能性があります。 プロキシが必要ないことがわかっている高スループット アプリケーションの場合は、プロキシを無効にする必要があります。

プロキシ設定 (同様 Credentials) は、HttpClient を使用して最初の要求が行われる前にのみ変更する必要があります。 HttpClient を初めて使用した後に行われた変更は、後続の要求には反映されない場合があります。

Timeouts

HttpClient インスタンスからのすべての HTTP 要求の既定のタイムアウトを設定するために使用 Timeout できます。 タイムアウトは、要求/応答が開始される xxxAsync メソッドにのみ適用されます。 タイムアウトに達すると、 Task<TResult> その要求の要求は取り消されます。

HttpClient オブジェクトを構築するときにインスタンスを渡す場合は、 SocketsHttpHandler いくつかの追加のタイムアウトを設定できます。

プロパティ 説明
ConnectTimeout 要求で新しい TCP 接続を作成する必要がある場合に使用されるタイムアウトを指定します。 タイムアウトが発生した場合、要求 Task<TResult> は取り消されます。
PooledConnectionLifetime 接続プール内の各接続に使用するタイムアウトを指定します。 接続がアイドル状態の場合、接続はすぐに閉じられます。それ以外の場合、接続は現在の要求の最後に閉じられます。
PooledConnectionIdleTimeout 接続プール内の接続がこの長い間アイドル状態の場合、接続は閉じられます。
Expect100ContinueTimeout 要求に "Expect: 100-continue" ヘッダーがある場合、タイムアウトになるまで、または "100-continue" 応答が受信されるまで、コンテンツの送信が遅れます。

HttpClient は、接続の作成時にのみ DNS エントリを解決します。 DNS サーバーによって指定されている有効期限 (TTL) の期間は追跡されません。 一部のコンテナー シナリオで発生する可能性がある DNS エントリが定期的に変更されている場合は、接続の PooledConnectionLifetime 交換時に DNS 参照が必要になるように、接続の有効期間を制限するために使用できます。