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

Rust调用本地C# gRPC服务遇HTTPS/HTTP连接错误求助

解决Tonic调用C# gRPC服务的连接问题

一、HTTPS连接错误(InvalidCertificate(NotValidForName))

错误根源有两点:

  • 自签名证书不被Rust的TLS信任链认可
  • 你使用127.0.0.1访问,但默认localhost自签名证书的有效域名仅为localhost,导致域名匹配失败

解决方案:跳过证书验证+使用localhost地址

修改Rust代码,自定义TLS配置跳过所有证书校验,同时将连接地址改为localhost:

首先在Cargo.toml补充依赖:

[dependencies]
tonic = "0.9"
prost = "0.12"
chrono = "0.4"
rustls = "0.21"
tokio = { version = "1.0", features = ["full"] }

然后替换客户端代码:

use gateway::notification_client::NotificationClient;
use gateway::LogRequest;
use prost_types::Timestamp;
use rustls::client::{ServerCertVerified, ServerCertVerifier};
use rustls::{Certificate, Error as RustlsError, ServerName};
use std::time::SystemTime;

pub mod gateway {
    tonic::include_proto!("log");
}

// 自定义验证器,完全跳过证书校验
struct NoopVerifier;

impl ServerCertVerifier for NoopVerifier {
    fn verify_server_cert(
        &self,
        _end_entity: &Certificate,
        _intermediates: &[Certificate],
        _server_name: &ServerName,
        _scts: &mut dyn Iterator<Item = &[u8]>,
        _ocsp_response: &[u8],
        _now: SystemTime,
    ) -> Result<ServerCertVerified, RustlsError> {
        Ok(ServerCertVerified::assertion())
    }
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 构建跳过验证的TLS配置
    let tls_config = rustls::ClientConfig::builder()
        .with_safe_defaults()
        .with_custom_certificate_verifier(std::sync::Arc::new(NoopVerifier))
        .with_no_client_auth();

    // 使用localhost地址匹配证书域名
    let channel = tonic::transport::Channel::from_static("https://localhost:7082")
        .tls_config(tls_config)?
        .connect()
        .await?;

    let mut client = NotificationClient::new(channel);

    let current_time = chrono::Utc::now();
    let timestamp = Timestamp {
        seconds: current_time.timestamp(),
        nanos: 0,
    };
    let request = tonic::Request::new(LogRequest {
        service_message: "TestServer2".into(),
        service_name: "TextToSpeach".into(),
        time: Some(timestamp)
    });

    let response = client.save_log_to_rabbit(request).await?;

    println!("RESPONSE={:?}", response);

    Ok(())
}

二、HTTP连接错误(endpoint requires HTTP/1.1)

错误原因:gRPC强制依赖HTTP/2协议,但你的C# gRPC服务默认仅在HTTPS下启用HTTP/2,未开启明文HTTP/2(h2c)支持。

解决方案:启用C#服务h2c支持+Rust端强制HTTP/2明文连接

  1. 修改C#服务的Kestrel配置(Program.cs):
var builder = WebApplication.CreateBuilder(args);

builder.Services.AddGrpc();

// 配置Kestrel监听HTTP/2明文
builder.WebHost.ConfigureKestrel(options =>
{
    options.ListenLocalhost(7082, o =>
    {
        o.Protocols = Microsoft.AspNetCore.Server.Kestrel.Core.HttpProtocols.Http2;
    });
});

var app = builder.Build();

app.MapGrpcService<NotificationService>();

app.Run();
  1. 修改Rust客户端代码,强制使用HTTP/2明文连接:
use gateway::notification_client::NotificationClient;
use gateway::LogRequest;
use prost_types::Timestamp;

pub mod gateway {
    tonic::include_proto!("log");
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 强制HTTP/2明文连接
    let channel = tonic::transport::Channel::from_static("http://localhost:7082")
        .connect_with_http2()
        .await?;

    let mut client = NotificationClient::new(channel);

    let current_time = chrono::Utc::now();
    let timestamp = Timestamp {
        seconds: current_time.timestamp(),
        nanos: 0,
    };
    let request = tonic::Request::new(LogRequest {
        service_message: "TestServer2".into(),
        service_name: "TextToSpeach".into(),
        time: Some(timestamp)
    });

    let response = client.save_log_to_rabbit(request).await?;

    println!("RESPONSE={:?}", response);

    Ok(())
}

总结

如果不想修改C#服务,优先选择HTTPS跳过证书验证的方案;若偏好HTTP连接,再选择启用h2c的方案,两种都能满足学习项目的无安全要求场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 08:41:06