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明文连接
- 修改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();
- 修改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
相关产品推荐
相关产品推荐

