1、安装依赖

对于 asp.net core 服务端项目安装以下即可,Grpc.AspNetCore 元包中包含对 Grpc.Tools 的引用。 服务器项目可以使用 Visual Studio 中的包管理器或通过将 Grpc.AspNetCore 添加到项目文件来添加<PackageReference>

1
<PackageReference Include="Grpc.AspNetCore" Version="2.32.0" />

客户端项目应直接引用 Grpc.Tools 以及使用 gRPC 客户端所需的其他包。 运行时不需要工具包,因此依赖项标记为 PrivateAssets="All"

1
2
3
4
5
6
<PackageReference Include="Google.Protobuf" Version="3.18.0" />
<PackageReference Include="Grpc.Net.Client" Version="2.52.0" />
<PackageReference Include="Grpc.Tools" Version="2.40.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>

2、gRPC 服务端

创建一个 Asp.Net Core 应用

添加 Protos 和 Services 文件夹,Protos 文件夹下存放 .proto 文件,Services 文件夹下存放 grpc 服务的实现

安装 Grpc.AspNetCorenuget 包

在 Protos 文件夹下创建 greet.proto 文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
syntax = "proto3";

option csharp_namespace = "GrpcGreeter";// 命名空间

package greet;

// 服务名
service Greeter {
// 定义方法
rpc SayHello (HelloRequest) returns (HelloReply);
}

// The request message containing the user's name.
message UserRequest {
string name = 1;
}

// The response message containing the greetings.
message UserReply {
string message = 1;
}

.csproj 项目文件中添加 Protobuf 引用 .proto 文件,默认情况下,会为 .proto 项组中包含的每个<Protobuf>文件都生成服务器和客户端资产。 若要确保服务器项目中仅生成服务器资产,请将 GrpcServices 属性设置为Server

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>

// 指定.proto文件的位置
<ItemGroup>
<Protobuf Include="Protos\greet.proto" GrpcServices="Server" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Grpc.AspNetCore" Version="2.57.0" />
</ItemGroup>

</Project>

编写 GrpcGreeter 实现业务功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
using Grpc.Core;
using GrpcGreeter;

namespace GrpcGreeter.Services
{
// Greeter.GreeterBase由系统运行时生成,我们需要编写实现这个类的服务
public class GreeterService : Greeter.GreeterBase
{
private readonly ILogger<GreeterService> _logger;
public GreeterService(ILogger<GreeterService> logger)
{
_logger = logger;
}
// 实现SayHello方法
public Task<HelloReply> SayHello(HelloRequest request, ServerCallContext context)
{
return Task.FromResult(new HelloReply
{
Message = "Hello " + request.Name
});
}
}
}

至此完成一个简单服务端代码的编写
工具包会生成表示在所包含 .proto 文件中定义的消息的 C# 类型。
对于服务器端资产,会生成抽象服务基类型。 基类型包含 .proto 文件中所含的所有 gRPC 调用的定义。 创建一个派生自此基类型并为 gRPC 调用实现逻辑的具体服务实现。 对于 greet.proto(前面所述的示例),会生成一个包含虚拟 GreeterBase 方法的抽象 SayHello 类型。 具体实现 GreeterService 会替代该方法,并实现处理 gRPC 调用的逻辑。

3、gRPC 客户端

客户端需要复制服务器端的.proto 文件,注意命名空间需要为对应客户端的命名空间

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
syntax = "proto3";

option csharp_namespace = "GrpcGreeterClient";

package greet;

// The greeting service definition.
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply);
}

// The request message containing the user's name.
message HelloRequest {
string name = 1;
}

// The response message containing the greetings.
message HelloReply {
string message = 1;
}

在.csproj 项目文件中添加 Protobuf 引用.proto 文件,注意工作模式设置为 Client

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Google.Protobuf" Version="3.33.2" />
<PackageReference Include="Grpc.Net.Client" Version="2.71.0" />
<PackageReference Include="Grpc.Tools" Version="2.76.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>

<ItemGroup>
<Protobuf Include="Protos\greet.proto" GrpcServices="Client" /> // 这里设置为Client
</ItemGroup>

</Project>

以控制台客户端为例,可以写出下面的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
using Grpc.Net.Client;
using GrpcGreeterClient;

// The port number must match the port of the gRPC server.
using var channel = GrpcChannel.ForAddress("https://localhost:7268");
// 创建对应服务的客户端
var client = new Greeter.GreeterClient(channel);
// 调用服务方法
var reply = await client.SayHelloAsync(
new HelloRequest { Name = "GreeterClient" });
Console.WriteLine("Greeting: " + reply.Message);
Console.WriteLine("Press any key to exit...");
Console.ReadKey();

对于客户端资产,会生成一个具体客户端类型。 .proto 文件中的 gRPC 调用会转换为具体类型中的方法,可以进行调用。 对于 greet.proto(前面所述的示例),会生成一个 GreeterClient 类型。 调用 GreeterClient.SayHelloAsync 以发起对服务器的 gRPC 调用。