用 dotnet new grpc 创建项目是最直接起点,生成含 greeterservice 的完整 grpc 服务,需注意 https/http/2 配置、.proto 文件位置与生成操作、服务注册 app.mapgrpcservice()、客户端必须通过 grpcchannel 调用、正确处理 statuscode=unavailable(连接问题)与 internal(服务端异常)。

用 dotnet new grpc 创建基础服务项目
这是最直接的起点,命令会生成包含 GreeterService 示例的完整可运行 gRPC 服务(基于 ASP.NET Core)。
执行后你会得到一个带 Program.cs、Protos/greet.proto 和 Services/GreeterService.cs 的项目。关键点在于:它默认启用 HTTPS 和 HTTP/2,且 app.MapGrpcService<greeterservice>()</greeterservice> 是注册服务的必需调用。
- 若在非开发环境部署,需确保服务器支持 HTTP/2(如 Kestrel 默认支持,IIS 需 Windows Server 2016+ + TLS 1.2+)
-
.proto文件必须放在Protos/目录并设为Protobuf生成操作,否则dotnet build不会生成 C# 绑定类 - 不要手动修改生成的
*.Grpc.cs文件——它们每次构建都会被覆盖
定义接口时注意 service 和 rpc 的写法
gRPC 的契约由 .proto 文件驱动,C# 类型和行为完全由此决定。错误的 proto 定义会导致客户端和服务端无法通信,甚至编译不报错但运行时报 StatusCode=Unimplemented。
常见问题包括:
千博购物系统.Net能够适合不同类型商品,为您提供了一个完整的在线开店解决方案。千博购物系统.Net除了拥有一般网上商店系统所具有的所有功能,还拥有着其它网店系统没有的许多超强功能。千博购物系统.Net适合中小企业和个人快速构建个性化的网上商店。强劲、安全、稳定、易用、免费是它的主要特性。系统由C#及Access/MS SQL开发,是B/S(浏览器/服务器)结构Asp.Net程序。多种独创的技术使
- 遗漏
option csharp_namespace = "MyApp.Protos";—— 导致生成的 C# 类不在预期命名空间,引用失败 -
rpc SayHello(HelloRequest) returns (HelloReply);中的HelloRequest和HelloReply必须已用message正确定义,且字段名首字母小写(如string name = 1;→ C# 属性为Name) - 流式方法要显式标注:比如
rpc StreamingCall(stream ClientMessage) returns (stream ServerMessage);,否则生成器不会产生IAsyncStreamReader或IServerStreamWriter
客户端调用必须用 Channel + 生成的 *Client 类
不能像调用普通类一样 new 一个服务类;必须通过 GrpcChannel.ForAddress("https://localhost:5001") 创建通道,再传给生成的客户端构造函数。
典型调用模式:
using var channel = GrpcChannel.ForAddress("https://localhost:5001");
var client = new Greeter.GreeterClient(channel);
var reply = await client.SayHelloAsync(new HelloRequest { Name = "Alice" });
- HTTP/2 要求地址协议明确:用
https://(开发时可配http://,但需在channel构造时加new GrpcChannelOptions { HttpHandler = new SocketsHttpHandler { EnableMultipleHttp2Connections = true } }) - 若服务启用了 TLS 但客户端证书验证失败,会抛
System.Net.Http.HttpRequestException,提示 “The SSL connection could not be established” —— 此时需配置GrpcChannelOptions.Credentials或临时禁用验证(仅限开发) - 短生命周期调用建议复用
GrpcChannel实例(它是线程安全的),不要为每次请求新建 channel
调试时先确认 StatusCode=Internal 还是 StatusCode=Unavailable
这两个错误看起来像网络问题,但根源完全不同:
-
StatusCode=Unavailable:通常是连接失败(地址错、端口未监听、防火墙拦截、TLS 协商失败),检查dotnet run是否真在监听,用curl -v https://localhost:5001看是否返回 HTTP/2 404(说明服务起来了) -
StatusCode=Internal:大概率是服务端代码异常未捕获,比如SayHello方法里 throw 了未处理的Exception—— gRPC 会将其转为Internal并丢掉原始堆栈;应在服务端添加全局异常过滤器或日志中间件捕获 - 客户端收到异常时,
exception.Status.Detail可能含服务端返回的错误信息(前提是服务端用了Status(StatusCode.Internal, "xxx")显式设置)
proto 文件改了之后,务必重新生成客户端和服务端代码;Visual Studio 不总会自动触发,可手动运行 dotnet build 或右键 .proto 文件选 “重新生成”。









