从零构建 gRPC 跨语言通信:C++ 服务端与 C# 客户端完整指南
【摘要】 前言 一、环境准备 必要工具安装 二、定义服务接口 创建 proto 文件 三、C++ 服务端实现 1. 生成 gRPC 代码 2. 实现服务逻辑 3. 实现服务端主程序 4. 编译服务端 四、C# 客户端实现 1. 创建 C# 项目 2. 添加 proto 文件 3. 实现客户端 4. 运行客户端 五、测试与验证 六、常见问题解决 1. 连接失败 2. 序列化错误 3. 性能优化 七、总...
前言
在现代分布式系统中,gRPC 作为高性能、跨语言的 RPC 框架越来越受欢迎。本文将手把手教你如何从零开始构建一个完整的 gRPC 通信系统,使用 C++ 实现服务端,C# 实现客户端。
一、环境准备
必要工具安装
-
Protocol Buffers 编译器 (protoc):
- 下载地址:https://github.com/protocolbuffers/protobuf/releases
- 确保将 protoc 添加到系统 PATH
-
gRPC 相关工具:
- C++:安装 gRPC 和 protobuf 库
# Ubuntu sudo apt install libgrpc++-dev libprotobuf-dev protobuf-compiler grpc-plugins
-
.NET 环境:
- 安装 .NET SDK (≥ 6.0)
- 添加 Grpc.Tools NuGet 包
二、定义服务接口
创建 proto 文件
创建 sample_service.proto
:
syntax = "proto3";
option csharp_namespace = "SampleService.Client";
package sampleservice;
// 请求消息
message CalculationRequest {
double a = 1;
double b = 2;
}
// 响应消息
message CalculationResult {
double result = 1;
}
// 服务定义
service Calculator {
// 加法运算
rpc Add (CalculationRequest) returns (CalculationResult);
// 减法运算
rpc Subtract (CalculationRequest) returns (CalculationResult);
}
三、C++ 服务端实现
1. 生成 gRPC 代码
创建 generate.sh
:
#!/bin/bash
protoc -I=. --grpc_out=. --plugin=protoc-gen-grpc=`which grpc_cpp_plugin` sample_service.proto
protoc -I=. --cpp_out=. sample_service.proto
运行后会生成:
sample_service.grpc.pb.h
sample_service.grpc.pb.cc
sample_service.pb.h
sample_service.pb.cc
2. 实现服务逻辑
创建 calculator_service.h
:
#include <grpcpp/grpcpp.h>
#include "sample_service.grpc.pb.h"
using grpc::ServerContext;
using grpc::Status;
using sampleservice::CalculationRequest;
using sampleservice::CalculationResult;
using sampleservice::Calculator;
class CalculatorServiceImpl final : public Calculator::Service {
public:
Status Add(ServerContext* context,
const CalculationRequest* request,
CalculationResult* response) override;
Status Subtract(ServerContext* context,
const CalculationRequest* request,
CalculationResult* response) override;
};
创建 calculator_service.cpp
:
#include "calculator_service.h"
Status CalculatorServiceImpl::Add(ServerContext* context,
const CalculationRequest* request,
CalculationResult* response) {
double result = request->a() + request->b();
response->set_result(result);
return Status::OK;
}
Status CalculatorServiceImpl::Subtract(ServerContext* context,
const CalculationRequest* request,
CalculationResult* response) {
double result = request->a() - request->b();
response->set_result(result);
return Status::OK;
}
3. 实现服务端主程序
创建 server.cpp
:
#include <iostream>
#include <memory>
#include <string>
#include <grpcpp/grpcpp.h>
#include "calculator_service.h"
using grpc::Server;
using grpc::ServerBuilder;
using grpc::ServerContext;
using grpc::Status;
void RunServer() {
std::string server_address("0.0.0.0:50051");
CalculatorServiceImpl service;
ServerBuilder builder;
builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());
builder.RegisterService(&service);
std::unique_ptr<Server> server(builder.BuildAndStart());
std::cout << "Server listening on " << server_address << std::endl;
server->Wait();
}
int main() {
RunServer();
return 0;
}
4. 编译服务端
创建 CMakeLists.txt
:
cmake_minimum_required(VERSION 3.10)
project(grpc_server)
set(CMAKE_CXX_STANDARD 17)
find_package(Protobuf REQUIRED)
find_package(gRPC REQUIRED)
add_executable(server
server.cpp
calculator_service.cpp
sample_service.pb.cc
sample_service.grpc.pb.cc
)
target_link_libraries(server
PRIVATE
gRPC::grpc++
gRPC::grpc
protobuf::libprotobuf
)
编译运行:
mkdir build && cd build
cmake .. && make
./server
四、C# 客户端实现
1. 创建 C# 项目
dotnet new console -n GrpcClient
cd GrpcClient
dotnet add package Grpc.Net.Client
dotnet add package Google.Protobuf
dotnet add package Grpc.Tools
2. 添加 proto 文件
将 sample_service.proto
放入项目目录,修改 .csproj
:
<ItemGroup>
<Protobuf Include="sample_service.proto" GrpcServices="Client" />
</ItemGroup>
3. 实现客户端
修改 Program.cs
:
using System;
using System.Threading.Tasks;
using Grpc.Net.Client;
using SampleService.Client;
class Program
{
static async Task Main(string[] args)
{
using var channel = GrpcChannel.ForAddress("http://localhost:50051");
var client = new Calculator.CalculatorClient(channel);
try
{
// 加法示例
var addRequest = new CalculationRequest { A = 5, B = 3 };
var addResult = await client.AddAsync(addRequest);
Console.WriteLine($"5 + 3 = {addResult.Result}");
// 减法示例
var subRequest = new CalculationRequest { A = 10, B = 4 };
var subResult = await client.SubtractAsync(subRequest);
Console.WriteLine($"10 - 4 = {subResult.Result}");
}
catch (Grpc.Core.RpcException ex)
{
Console.WriteLine($"RPC failed: {ex.Status.Detail}");
}
}
}
4. 运行客户端
dotnet run
五、测试与验证
- 首先启动 C++ 服务端
- 然后运行 C# 客户端
预期输出:
5 + 3 = 8
10 - 4 = 6
六、常见问题解决
1. 连接失败
- 确保服务端地址正确
- 检查防火墙设置
- 服务端和客户端使用相同的协议(HTTP/HTTPS)
2. 序列化错误
- 确保 proto 文件在服务端和客户端完全一致
- 重新生成代码后清理并重新编译
3. 性能优化
- 对于高频调用,考虑使用连接池
- 调整 gRPC 通道参数
七、总结
通过本文,我们完成了:
- 定义 gRPC 服务接口
- 实现 C++ 服务端
- 实现 C# 客户端
- 建立跨语言通信
这个示例展示了 gRPC 的核心功能,你可以基于此扩展更复杂的业务逻辑。gRPC 的强大之处在于它的跨语言特性和高性能通信能力,非常适合微服务架构。
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)