.NET 10 网络改进:HTTP、安全与网络原语的全面升级

.NET 10 网络改进:HTTP、安全与网络原语的全面升级

引言

随着.NET 10的发布,微软在网络技术栈上带来了一系列令人兴奋的改进和新增功能。这些改进覆盖了HTTP协议处理、WebSockets API、安全增强以及网络基础原语等多个方面。本文将深入探讨这些技术改进,帮助开发者更好地理解和利用.NET 10在网络编程方面的最新能力。

HTTP改进

WinHttpHandler性能优化

.NET 10中对WinHttpHandler的服务器证书验证进行了显著优化。通常情况下,证书验证由原生WinHTTP实现处理,但当用户代码通过ServerCertificateValidationCallback注册自定义验证逻辑时,系统会跳过内部验证流程。由于原生WinHTTP缺乏对应连接建立的事件,托管层不得不在每个请求中调用自定义回调,这导致了性能开销。

为解决这一问题,.NET 10引入了基于服务器IP地址的已验证证书缓存机制。当发送新请求时,如果证书已被验证过,WinHttpHandler将跳过证书链构建和自定义回调调用。此外,每次新连接都会清除该服务器IP的缓存证书,确保在连接重建时重新验证。

这一优化功能默认关闭,需要通过AppContext开关启用:

AppContext.SetSwitch("System.Net.Http.UseWinHttpCertificateCaching", true);

测试表明,启用此功能后,证书验证回调仅调用一次,而非每次请求都调用,显著提升了性能。

新增HTTP动词QUERY

.NET 10引入了新的HTTP动词QUERY,允许在请求体中发送查询细节,同时保持请求的安全性和幂等性。这在查询细节超出URI长度限制或服务器不支持GET请求体时特别有用。由于QUERY方法仍在标准化过程中,.NET 10目前仅添加了字符串常量供开发者使用:

using var client = new HttpClient();
var response = await client.SendAsync(new HttpRequestMessage(HttpMethod.Query, "https://api.example.com/resource"));

Cookie改进

一个小但实用的改进是将CookieException构造函数公开化,允许开发者手动抛出Cookie异常:

throw new CookieException("🍪");

WebSockets改进

WebSocketStream抽象

.NET 10引入了WebSocketStream,这是一个基于流的WebSocket抽象层,大大简化了文本和二进制协议的数据读写操作。主要优势包括:

  1. 流优先设计:与StreamReader、JsonSerializer等无缝协作
  2. 自动化处理:消除了消息帧和剩余数据处理的手工操作
  3. 多场景支持:支持JSON协议、STOMP类文本协议和AMQP类二进制协议

常见使用模式

读取完整JSON消息

using Stream message = WebSocketStream.CreateReadableMessageStream(ws);
return await JsonSerializer.DeserializeAsync<AppMessage>(message, cancellationToken: ct);

流式文本协议处理

// 使用Create获取传输流,并叠加StreamReader
// 可在保持流开放的情况下逐行解析

写入二进制消息

// 使用CreateWritableMessageStream逐块写入
// Dispose会自动发送消息结束标志

与传统方式相比,WebSocketStream通过流抽象消除了缓冲、复制和EndOfMessage检查等手工操作,大大简化了代码。

安全增强

OSX上的客户端TLS 1.3支持

TLS 1.3在OSX上的支持是长期被请求的功能(dotnet/runtime#1979)。由于实现上的挑战,包括需要切换到不同的原生OSX API,以及这些API将TLS与TCP层耦合而.NET将它们作为独立层(SslStream和Socket)暴露,这一功能被设计为通过AppContext开关启用的可选特性:

代码启用方式:

AppContext.SetSwitch("System.Net.Security.UseNetworkFramework", true);

或环境变量方式:

export DOTNET_SYSTEM_NET_SECURITY_USENETWORKFRAMEWORK=1

注意此功能仅影响OSX上的客户端操作,且仅支持TLS 1.3和1.2。

协商密码套件统一

SslStream原先提供多个属性(KeyExchangeAlgorithm、HashAlgorithm等)来描述协商的密码套件,但这些属性的底层枚举未能准确反映最新标准。.NET 10弃用了这些属性,仅保留NegotiatedCipherSuite作为唯一真实来源。该枚举遵循IANA的TLS密码套件规范,包含所有必要信息。

同样的属性也被添加到QuicConnection中(dotnet/runtime#106391),为建立的连接提供协商的TLS细节。

网络原语改进

服务器发送事件(SSE)格式化器

继.NET上版本添加SSE解析器后,.NET 10引入了SSE格式化器(dotnet/runtime#109294)。最简单的字符串数据场景使用示例如下:

using var stream = new MemoryStream();
await SseFormatter.WriteAsync(GetStringItems(), stream);

static async IAsyncEnumerable<SseItem<string>> GetStringItems()
{
    yield return new SseItem<string>("data 1");
    // ...
}

对于非字符串数据,需要提供格式化委托:

await SseFormatter.WriteAsync<int>(GetItems(), stream, (item, writer) => 
{
    writer.Write(Encoding.UTF8.GetBytes(item.Data.ToString()));
});

SseItem新增了两个属性:

  • EventId:发送id字段
  • ReconnectionInterval:发送retry字段

这些字段控制客户端在连接需要重建时的行为,使得System.Net.ServerSentEvents为通信双方提供了完整的辅助工具集。

IP地址验证

IPAddress类新增了两个实用方法:

if (IPAddress.IsValid("10.0.0.1")) { ... }
if (IPAddress.IsValidUtf8("::1"u8)) { ... }

此外,IPAddress和IPNetwork现在实现了IUtf8SpanParsable接口,这是对.NET 8添加的IUtf8SpanFormattable的补充。

其他改进

  1. URI长度限制取消:支持RFC 2397规定的data URI方案,允许在URI中直接嵌入数据(如base64编码图像)
  2. 新增YAML媒体类型:添加了MediaTypesName.Yaml常量(dotnet/runtime#117211)

结论

.NET 10在网络技术栈上带来了全方位的改进,从HTTP性能优化到WebSocket API简化,从安全增强到基础网络原语的功能扩展。这些改进不仅提升了性能,也大大简化了开发者的工作流程,使得构建高效、安全的网络应用更加容易。

posted @ 2025-12-10 11:25  葡萄城技术团队  阅读(120)  评论(0)    收藏  举报