.NET 8 のネットワーク機能強化:SocketsHttpHandler、QUIC、UDP ソケット、IPNetwork

SocketsHttpHandler の設定簡略化

.NET 8 では、HttpClientFactorySocketsHttpHandler をより直感的に設定できるようになりました(dotnet/runtime#84075)。

UseSocketsHttpHandler メソッドにより、コード内または設定ファイル(IConfiguration)からハンドラを構成できます。両方を組み合わせることも可能です。

設定ファイルからの読み込みは、boolintEnumTimeSpan 型のプロパティに限定され、それ以外は無視されます。また、設定はアプリケーション起動時に一度だけ読み込まれ、実行中に変更しても反映されません。

// コードで直接設定
services.AddHttpClient("clientA")
    .UseSocketsHttpHandler((handler, _) => handler.UseCookies = false);

// 設定とコードの組み合わせ
services.AddHttpClient("clientB")
    .UseSocketsHttpHandler(builder =>
        builder.Configure(config.GetSection("HttpClients:clientB"))
               .Configure((handler, _) =>
               {
                   handler.SslOptions.RemoteCertificateValidationCallback = (_, _, _, _) => true;
               }));
{
  "HttpClients": {
    "clientB": {
      "AllowAutoRedirect": true,
      "UseCookies": false,
      "ConnectTimeout": "00:00:05"
    }
  }
}

QUIC の改善

OpenSSL 3 対応

主要な Linux ディストリビューション(Debian 12+、Ubuntu 22+、Fedora 37+ など)が OpenSSL 3 を採用したことを受け、.NET 8 の QUIC 実装(MsQuic)も対応しました(dotnet/runtime#81801)。

MsQuic は各ディストリビューションの OpenSSL バージョンに応じたネイティブライブラリ(libmsquic)を提供しており、例えば Debian 12 では OpenSSL 3 に依存します。

例外処理の統一

.NET 8 では System.Net.Quic の例外モデルが見直され、一貫性が向上しました(dotnet/runtime#82262)。

  • QuicException:QUIC プロトコル固有のエラー(接続切断、ストリーム中止など)
  • SocketException:ネットワーク層の問題(ホスト名解決失敗、アドレス使用中など)
  • AuthenticationException:TLS 関連エラー(証明書不正、ALPN 失敗など)
  • ArgumentException:オプション設定ミス(無効なストリーム数、必須フィールド未指定など)
  • OperationCanceledException:キャンセル要求時
  • ObjectDisposedException:破棄済みオブジェクトへの操作時

さらに、QuicError.CallbackError が追加され、ユーザー定義のコールバック内で発生した例外を識別できるようになりました(dotnet/runtime#88614)。

var listener = await QuicListener.ListenAsync(new QuicListenerOptions
{
    ConnectionOptionsCallback = (_, hello, _) =>
    {
        if (blockedHosts.Contains(hello.ServerName))
            throw new ArgumentException($"Blocked host: {hello.ServerName}");
        return ValueTask.FromResult(new QuicServerConnectionOptions());
    }
});

try
{
    await listener.AcceptConnectionAsync();
}
catch (QuicException ex) when (ex.QuicError == QuicError.CallbackError && ex.InnerException is ArgumentException)
{
    Console.WriteLine($"拒否された接続: {ex.InnerException.Message}");
}

また、RFC 9000 で定義されるトランスポートエラーコードが QuicException.TransportErrorCode プロパティとして公開されました(dotnet/runtime#88550)。

UDP ソケットのパフォーマンス向上

UDP 通信時のメモリ割り当てを削減するため、SocketAddress を使う新しい API が導入されました(dotnet/runtime#87397)。

従来の ReceiveFromAsync は毎回 IPEndPoint を生成していましたが、新 API は再利用可能な SocketAddress をインプレースで更新します。

var server = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
var client = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
var endpoint = new IPEndPoint(IPAddress.Loopback, 12345);
server.Bind(endpoint);

byte[] buffer = new byte[1024];
byte[] message = Encoding.UTF8.GetBytes("Hello");

// 新しい方法:SocketAddress を再利用
var recvAddr = endpoint.Serialize();
var targetAddr = endpoint.Serialize();

await client.SendToAsync(message, SocketFlags.None, targetAddr);
int received = await server.ReceiveFromAsync(buffer, SocketFlags.None, recvAddr);

Console.WriteLine($"{Encoding.UTF8.GetString(buffer, 0, received)} from {recvAddr}");

SocketAddress 自体も拡張され、BufferSizeGetMaximumAddressSize()IEquatable<SocketAddress> が追加されました(dotnet/runtime#86872)。

ネットワーク関連の新機能

MIME タイプの拡充

コミュニティ主導で、IANA 登録済みの MIME タイプが多数追加されました(dotnet/runtime#85807)。

IPNetwork 型の導入

RFC 4632 に基づく CIDR 表記のサブネットを扱う IPNetwork 構造体が追加されました(dotnet/runtime#79946)。

// IPv4
var net = new IPNetwork(IPAddress.Parse("127.0.0.0"), 8);
Console.WriteLine(net.Contains(IPAddress.Parse("127.0.0.10"))); // True
Console.WriteLine(net.Contains(IPAddress.Parse("255.0.0.1")));  // False

// IPv6
var net6 = IPNetwork.Parse("2a01:110:8012::/96");
Console.WriteLine(net6.Contains(IPAddress.Parse("2a01:110:8012::1742:4244"))); // True
Console.WriteLine(net6.Contains(IPAddress.Parse("2a01:110:8012:1010::1")));     // False

この型は ASP.NET Core の既存の Microsoft.AspNetCore.HttpOverrides.IPNetwork とは別物ですが、将来的には統合される予定です(dotnet/aspnetcore#46157)。

タグ: .NET 8 SocketsHttpHandler quic udp IPNetwork

8月16日 16:30 投稿