.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抽象层,大大简化了文本和二进制协议的数据读写操作。主要优势包括:
- 流优先设计:与StreamReader、JsonSerializer等无缝协作
- 自动化处理:消除了消息帧和剩余数据处理的手工操作
- 多场景支持:支持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
其他改进
- URI长度限制取消:支持RFC 2397规定的data URI方案,允许在URI中直接嵌入数据(如base64编码图像)
- 新增YAML媒体类型:添加了MediaTypesName.Yaml常量(dotnet/runtime#117211)
结论
.NET 10在网络技术栈上带来了全方位的改进,从HTTP性能优化到WebSocket API简化,从安全增强到基础网络原语的功能扩展。这些改进不仅提升了性能,也大大简化了开发者的工作流程,使得构建高效、安全的网络应用更加容易。
浙公网安备 33010602011771号