.NET 7 WinForms应用扩展为gRPC服务器时HTTP/2连接异常排查
.NET 7 WinForms 集成 gRPC 服务器的 HTTP/2 连接问题
我正在把基于.NET 7(C#)的WinForms应用扩展为gRPC服务器,作为胖客户端向客户端/服务器架构迁移的过渡方案,gRPC服务器无需与GUI交互。已添加必要的gRPC包并创建登录请求的proto文件,参照微软文档实现的gRPC服务器代码如下:
public class GrpcServerApp { private LoginService loginRPC; private WebApplication GrpcServer; public GrpcServerApp(GUI.Control control) { var builder = WebApplication.CreateBuilder(new string[] { }); builder.Services.AddGrpc(); builder.Services.AddAuthentication(CertificateAuthenticationDefaults.AuthenticationScheme) .AddCertificate() .AddCertificateCache(); GrpcServer = builder.Build(); GrpcServer.UseAuthentication(); GrpcServer.MapGrpcService<LoginService>(); GrpcServer.MapGet("/", () => "Communication with gRPC endpoints must be made through a gRPC client"); loginRPC = new LoginService(control); GrpcServer.StartAsync(); } }
(GUI.Control仅提供应用版本字符串)项目可正常构建,服务器监听5000端口并能响应HTTP根路径请求,但使用如下gRPC客户端代码连接时:
AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true); GrpcChannel channel = GrpcChannel.ForAddress(address); var client = new RPC.Login.LoginClient(channel); RPC.LoginResponse? response = null; try { response = await client.ClientLoginAsync( new RPC.LoginRequest { Name = UsernameTextBox.Text, }); }
出现错误:
HttpProtocolException: The HTTP/2 server closed the connection. HTTP/2 error code 'HTTP_1_1_REQUIRED' (0xd)'
我推测是HTTP版本不匹配,也怀疑HTTP/2需配合TLS,但不知如何配置;同时发现服务器仅监听HTTP的5000端口,而VS2022的gRPC模板项目会自动开启HTTPS端口,想问需要补充哪些配置才能建立正常的HTTP/2连接。
解决方案
错误码HTTP_1_1_REQUIRED的核心原因是:默认情况下Kestrel的HTTP端口仅启用HTTP/1.1协议,只有HTTPS端口才默认支持HTTP/2。针对需求,可选择以下两种配置方案:
方案一:配置HTTPS端口(生产环境推荐)
gRPC官方推荐在生产环境使用TLS加密,配置步骤如下:
- 修改服务器代码,添加Kestrel端口配置,启用HTTPS:
public GrpcServerApp(GUI.Control control) { var builder = WebApplication.CreateBuilder(new string[] { }); // 配置Kestrel监听HTTPS端口(用于gRPC)和HTTP端口(用于兼容HTTP请求) builder.WebHost.ConfigureKestrel(options => { options.ListenAnyIP(5001, o => o.UseHttps()); // HTTPS端口,默认支持HTTP/2 options.ListenAnyIP(5000); // HTTP端口,保留原有的HTTP/1.1支持 }); builder.Services.AddGrpc(); builder.Services.AddAuthentication(CertificateAuthenticationDefaults.AuthenticationScheme) .AddCertificate() .AddCertificateCache(); GrpcServer = builder.Build(); GrpcServer.UseAuthentication(); GrpcServer.MapGrpcService<LoginService>(); GrpcServer.MapGet("/", () => "Communication with gRPC endpoints must be made through a gRPC client"); loginRPC = new LoginService(control); GrpcServer.StartAsync(); }
- 调整客户端代码,使用HTTPS地址连接,无需保留无加密HTTP/2的开关:
// 移除这个开关:AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true); GrpcChannel channel = GrpcChannel.ForAddress("https://localhost:5001"); var client = new RPC.Login.LoginClient(channel); // 其余请求代码不变
- 开发环境可直接使用.NET自带的开发证书,运行时会自动信任;生产环境需配置有效的SSL证书。
方案二:允许无TLS的HTTP/2(仅开发测试用)
如果仅用于开发测试,可强制让HTTP端口支持HTTP/2:
- 修改服务器的Kestrel配置:
public GrpcServerApp(GUI.Control control) { var builder = WebApplication.CreateBuilder(new string[] { }); builder.WebHost.ConfigureKestrel(options => { options.ListenAnyIP(5000, o => { o.Protocols = HttpProtocols.Http1AndHttp2; // 同时启用HTTP/1.1和HTTP/2 }); }); // 其余服务器代码不变 }
- 客户端保持原有代码(保留
Http2UnencryptedSupport开关),连接地址仍使用http://localhost:5000即可。
内容的提问来源于stack exchange,提问作者jowo
相关产品推荐
相关产品推荐

