从零构建 gRPC 跨语言通信:C++ 服务端与 C# 客户端完整指南

举报
码事漫谈 发表于 2025/06/25 18:27:00 2025/06/25
【摘要】 前言 一、环境准备 必要工具安装 二、定义服务接口 创建 proto 文件 三、C++ 服务端实现 1. 生成 gRPC 代码 2. 实现服务逻辑 3. 实现服务端主程序 4. 编译服务端 四、C# 客户端实现 1. 创建 C# 项目 2. 添加 proto 文件 3. 实现客户端 4. 运行客户端 五、测试与验证 六、常见问题解决 1. 连接失败 2. 序列化错误 3. 性能优化 七、总...

前言

在现代分布式系统中,gRPC 作为高性能、跨语言的 RPC 框架越来越受欢迎。本文将手把手教你如何从零开始构建一个完整的 gRPC 通信系统,使用 C++ 实现服务端,C# 实现客户端。

一、环境准备

必要工具安装

  1. Protocol Buffers 编译器 (protoc)

  2. gRPC 相关工具

    • C++:安装 gRPC 和 protobuf 库
    # Ubuntu
    sudo apt install libgrpc++-dev libprotobuf-dev protobuf-compiler grpc-plugins
    
  3. .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

五、测试与验证

  1. 首先启动 C++ 服务端
  2. 然后运行 C# 客户端

预期输出:

5 + 3 = 8
10 - 4 = 6

六、常见问题解决

1. 连接失败

  • 确保服务端地址正确
  • 检查防火墙设置
  • 服务端和客户端使用相同的协议(HTTP/HTTPS)

2. 序列化错误

  • 确保 proto 文件在服务端和客户端完全一致
  • 重新生成代码后清理并重新编译

3. 性能优化

  • 对于高频调用,考虑使用连接池
  • 调整 gRPC 通道参数

七、总结

通过本文,我们完成了:

  1. 定义 gRPC 服务接口
  2. 实现 C++ 服务端
  3. 实现 C# 客户端
  4. 建立跨语言通信

这个示例展示了 gRPC 的核心功能,你可以基于此扩展更复杂的业务逻辑。gRPC 的强大之处在于它的跨语言特性和高性能通信能力,非常适合微服务架构。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。