SocketsHttpHandler の設定簡略化
.NET 8 では、HttpClientFactory で SocketsHttpHandler をより直感的に設定できるようになりました(dotnet/runtime#84075)。
UseSocketsHttpHandler メソッドにより、コード内または設定ファイル(IConfiguration)からハンドラを構成できます。両方を組み合わせることも可能です。
設定ファイルからの読み込みは、bool、int、Enum、TimeSpan 型のプロパティに限定され、それ以外は無視されます。また、設定はアプリケーション起動時に一度だけ読み込まれ、実行中に変更しても反映されません。
// コードで直接設定
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 自体も拡張され、Buffer、Size、GetMaximumAddressSize()、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)。