You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.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加密,配置步骤如下:

  1. 修改服务器代码,添加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();
}
  1. 调整客户端代码,使用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:

  1. 修改服务器的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
        });
    });

    // 其余服务器代码不变
}
  1. 客户端保持原有代码(保留Http2UnencryptedSupport开关),连接地址仍使用http://localhost:5000即可。

内容的提问来源于stack exchange,提问作者jowo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 20:40:26