ASP.NET Core 6中如何直接获取无HTTP协议的Socket流?
在.NET 6中获取HTTP升级后的原始Socket流
要实现自定义协议的HTTP升级并获取底层Socket流,你可以利用ASP.NET Core的IHttpUpgradeFeature特性,以下是具体实现步骤:
1. 配置中间件处理升级请求
在Program.cs中添加自定义中间件,拦截带有Upgrade和Connection: upgrade头部的请求:
var builder = WebApplication.CreateBuilder(args); var app = builder.Build(); // 自定义协议处理中间件 app.Use(async (context, next) => { // 检查是否是目标升级请求 var upgradeFeature = context.Features.Get<IHttpUpgradeFeature>(); if (upgradeFeature != null && context.Request.Headers.TryGetValue("Connection", out var connectionHeader) && connectionHeader.ToString().IndexOf("upgrade", StringComparison.OrdinalIgnoreCase) >= 0 && context.Request.Headers.TryGetValue("Upgrade", out var upgradeHeader) && upgradeHeader.ToString().Equals("myprotocol", StringComparison.OrdinalIgnoreCase)) { // 发送101协议切换响应 context.Response.StatusCode = StatusCodes.Status101SwitchingProtocols; context.Response.Headers.Append("Connection", "Upgrade"); context.Response.Headers.Append("Upgrade", "myprotocol"); // 获取升级后的原始Socket流 using var stream = await upgradeFeature.UpgradeAsync(); // 此处可直接读写stream,进行自定义协议通信 // 示例:读取客户端数据并返回 var buffer = new byte[1024]; int bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length); if (bytesRead > 0) { string receivedData = Encoding.UTF8.GetString(buffer, 0, bytesRead); var responseBytes = Encoding.UTF8.GetBytes($"Received: {receivedData}"); await stream.WriteAsync(responseBytes, 0, responseBytes.Length); await stream.FlushAsync(); } // 处理完成后直接返回,跳过后续中间件 return; } // 非升级请求,交给后续中间件处理 await next(context); }); app.Run();
关键说明
IHttpUpgradeFeature是ASP.NET Core的核心特性,专门用于处理HTTP协议升级场景,调用UpgradeAsync()返回的Stream就是底层Socket流,不再包含HTTP协议头。- 必须先返回
101 Switching Protocols状态码,并设置对应响应头部,完成协议切换的握手流程。 - 自定义协议名称(示例中的
myprotocol)需要客户端和服务端保持一致,确保升级逻辑能正确匹配。
客户端测试示例(C#)
你可以用以下代码测试服务端的自定义协议:
using var client = new TcpClient("localhost", 5000); using var stream = client.GetStream(); // 发送HTTP升级请求 var request = "GET / HTTP/1.1\r\n" + "Host: localhost:5000\r\n" + "Connection: Upgrade\r\n" + "Upgrade: myprotocol\r\n\r\n"; var requestBytes = Encoding.UTF8.GetBytes(request); await stream.WriteAsync(requestBytes, 0, requestBytes.Length); await stream.FlushAsync(); // 读取101响应头 var responseBuffer = new byte[1024]; int responseBytesRead = await stream.ReadAsync(responseBuffer, 0, responseBuffer.Length); string responseHeader = Encoding.UTF8.GetString(responseBuffer, 0, responseBytesRead); Console.WriteLine("响应头:\n" + responseHeader); // 发送自定义协议数据 var customData = "Hello Custom Protocol!"; var customDataBytes = Encoding.UTF8.GetBytes(customData); await stream.WriteAsync(customDataBytes, 0, customDataBytes.Length); await stream.FlushAsync(); // 读取服务端返回的自定义协议数据 var resultBuffer = new byte[1024]; int resultBytesRead = await stream.ReadAsync(resultBuffer, 0, resultBuffer.Length); string result = Encoding.UTF8.GetString(resultBuffer, 0, resultBytesRead); Console.WriteLine("服务端返回:" + result);
内容的提问来源于stack exchange,提问作者user1870379
相关产品推荐
相关产品推荐

