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

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

文章目录

前言

在现代分布式系统中,gRPC 作为高性能、跨语言的 RPC 框架越来越受欢迎。它基于 HTTP/2 协议,使用 Protocol Buffers(Protobuf)作为接口定义语言,支持多种编程语言,能够高效地实现不同语言之间的远程过程调用。本文将手把手教你如何从零开始构建一个完整的 gRPC 通信系统,使用 C++ 实现服务端,C# 实现客户端。

gRPC架构

一、环境准备

必要工具安装

1. Protocol Buffers 编译器 (protoc)

Protocol Buffers 是一种轻便高效的结构化数据存储格式,gRPC 使用它来定义服务接口和数据结构。你需要下载并安装 Protocol Buffers 编译器 protoc,下载地址为:https://github.com/protocolbuffers/protobuf/releases。安装完成后,确保将 protoc 添加到系统的 PATH 环境变量中,这样在命令行中就可以直接使用它。

2. gRPC 相关工具(C++)

对于 C++ 开发,你需要安装 gRPC 和 protobuf 库。在 Ubuntu 系统上,可以使用以下命令进行安装:

sudoaptinstall libgrpc++-dev libprotobuf-dev protobuf-compiler grpc-plugins 
3. .NET 环境

C# 开发需要安装 .NET SDK(版本 ≥ 6.0),你可以从 https://dotnet.microsoft.com/download 下载并安装。安装完成后,在 C# 项目中添加必要的 NuGet 包:

dotnet add package Grpc.Net.Client dotnet add package Google.Protobuf dotnet add package Grpc.Tools 

二、定义服务接口

创建 proto 文件

首先,我们需要创建一个 .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); } 

在这个 .proto 文件中,我们定义了一个名为 Calculator 的服务,包含两个方法:AddSubtract,分别用于执行加法和减法运算。同时,我们还定义了请求消息 CalculationRequest 和响应消息 CalculationResult

三、C++ 服务端实现

1. 生成 gRPC 代码

为了根据 .proto 文件生成 C++ 代码,我们需要创建一个脚本 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;classCalculatorServiceImplfinal: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;voidRunServer(){ 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();}intmain(){RunServer();return0;}

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# 项目

使用以下命令创建一个新的 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 文件复制到 C# 项目目录下,并修改 .csproj 文件,添加以下内容:

<ItemGroup><ProtobufInclude="sample_service.proto"GrpcServices="Client"/></ItemGroup>

3. 实现客户端

修改 Program.cs 文件,实现客户端代码:

usingSystem;usingSystem.Threading.Tasks;usingGrpc.Net.Client;usingSampleService.Client;classProgram{staticasyncTaskMain(string[] args){usingvar channel = GrpcChannel.ForAddress("http://localhost:50051");var client =newCalculator.CalculatorClient(channel);try{// 加法示例var addRequest =newCalculationRequest{ A =5, B =3};var addResult =await client.AddAsync(addRequest); Console.WriteLine($"5 + 3 = {addResult.Result}");// 减法示例var subRequest =newCalculationRequest{ 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++ 服务端

在终端中运行编译好的服务端程序:

./server 

服务端启动后,会监听 0.0.0.0:50051 端口。

2. 运行 C# 客户端

在另一个终端中,进入 C# 客户端项目目录,运行客户端程序:

dotnet run 

如果一切正常,你将看到以下输出:

5 + 3 = 8 10 - 4 = 6 

这表明客户端成功调用了服务端的方法,并得到了正确的结果。

六、常见问题解决

1. 连接失败

  • 确保服务端地址正确:检查客户端代码中指定的服务端地址和端口是否与服务端实际监听的地址和端口一致。
  • 检查防火墙设置:确保防火墙没有阻止客户端与服务端之间的通信。可以临时关闭防火墙进行测试,或者在防火墙中开放相应的端口。
  • 服务端和客户端使用相同的协议:确保客户端和服务端使用相同的协议(HTTP/HTTPS)。如果服务端使用的是不安全连接(InsecureServerCredentials),客户端也应该使用不安全连接。

2. 序列化错误

  • 确保 proto 文件在服务端和客户端完全一致.proto 文件是服务端和客户端通信的契约,必须保证两端的 .proto 文件内容完全相同。
  • 重新生成代码后清理并重新编译:如果修改了 .proto 文件,需要重新生成代码,并清理和重新编译服务端和客户端项目。

3. 性能优化

  • 对于高频调用,考虑使用连接池:gRPC 本身没有提供连接池的功能,但可以通过第三方库或自定义实现来实现连接池,以减少连接建立和销毁的开销。
  • 调整 gRPC 通道参数:可以根据实际情况调整 gRPC 通道的参数,如超时时间、最大消息大小等,以提高性能。

七、流程总结

以下是按照步骤,用表格形式总结的基于gRPC实现跨语言通信(C++服务端、C#客户端)的流程:

gRPC跨语言通信实现流程总结表

步骤任务具体内容详细描述
1. 环境准备安装必要的工具和库安装Protocol Buffers编译器(protoc),如在Windows系统中下载安装包并配置环境变量,使其可在命令行中直接调用;安装gRPC相关工具,包括gRPC插件(如grpc_cpp_plugingrpc_csharp_plugin),用于生成对应语言的源代码;安装.NET环境(如.NET SDK),用于C#客户端开发,可通过官网下载对应版本安装包并安装,安装完成后可通过命令行运行dotnet --version验证安装是否成功;此外,还需安装C++开发环境(如Visual Studio),用于C++服务端的开发,安装时选择对应的开发工作负载,如“桌面开发”等
2. 定义服务接口使用.proto文件定义服务接口和数据结构创建.proto文件来定义服务接口及数据结构,例如定义一个名为MyService的服务,其中包含一个SayHello方法,该方法接收一个HelloRequest消息类型作为参数,并返回一个HelloReply消息类型,.proto文件中会包含对应的message定义来具体描述HelloRequestHelloReply的字段,如string name字段等
3. 生成代码根据.proto文件生成C++和C#代码在命令行中使用protoc编译器,结合相应的gRPC插件来生成代码,对于C++,运行类似protoc --grpc_out=. --plugin=protoc-gen-grpc=grpc_cpp_plugin path/to/your/service.proto的命令,生成C++服务端的桩代码;对于C#,运行类似protoc --grpc_out=. --plugin=protoc-gen-grpc=grpc_csharp_plugin path/to/your/service.proto的命令,生成C#客户端的存根代码
4. 实现服务端在C++中实现服务端逻辑,并编译运行根据生成的C++桩代码,在C++项目中实现服务端的具体逻辑,如实现MyService服务中的SayHello方法的业务逻辑,编写一个SayHello的重写方法,在该方法中根据输入的HelloRequest来构造HelloReply作为返回值;之后配置C++项目的编译链接环境,添加必要的gRPC、Protocol Buffers库依赖等,编译生成服务端可执行文件,并运行服务端
5. 实现客户端在C#中实现客户端代码,并运行客户端进行测试根据生成的C#存根代码,在C#项目(如使用.NET SDK创建的控制台应用程序项目)中实现客户端逻辑,创建Channel连接到服务端地址,创建客户端实例,并调用服务端的方法,如调用SayHello方法,构造HelloRequest并发送请求,接收服务端返回的HelloReply;配置C#项目依赖,添加gRPC、Protocol Buffers相关的NuGet包引用,运行客户端进行测试
6. 测试与验证启动服务端和客户端,验证通信是否正常先启动服务端,确保服务端处于运行状态并监听端口;然后启动客户端,客户端会发送请求到服务端,服务端处理后返回响应给客户端,观察客户端是否能正确接收到预期的响应结果,如在控制台输出“Hello, [name]”之类的响应信息来验证通信是否成功
7. 问题解决遇到问题时,根据具体情况进行排查和解决如果服务端和客户端无法通信,可以检查网络连接是否正常,如端口是否被正确监听和连接;检查服务端和客户端的.proto文件版本是否一致,以及生成的代码是否正确;检查是否所有必要的依赖库都已正确安装和配置;通过查看日志信息、调试程序等方式来定位问题并解决,根据问题具体表现来逐步排查原因

希望这个表格能帮助你清晰地梳理整个gRPC跨语言通信实现的流程。

通过以上步骤,我们完成了一个完整的 gRPC 跨语言通信系统的搭建,实现了 C++ 服务端和 C# 客户端之间的通信。这个示例展示了 gRPC 的核心功能,你可以基于此扩展更复杂的业务逻辑。gRPC 的强大之处在于它的跨语言特性和高性能通信能力,非常适合微服务架构。

Read more

2025年AI领域年度深度总结:始于DeepSeek R1开源发布,终于Manus天价出海

2025年AI领域年度深度总结:始于DeepSeek R1开源发布,终于Manus天价出海

2025年AI领域年度深度总结:始于DeepSeek R1开源发布,终于Manus天价出海 摘要 站在2025年12月31日的终章回望,吴恩达曾说过:“2025年,是AI工业时代的黎明。”在经历了2023-2024年的“大炼模型”狂热后,2025年,AI终于从“概率模仿”跃向了“逻辑推理”的新阶段,从“对话框”到“行动流”的转折也逐渐显现。这一年,AI技术与产业的演进不仅仅是技术迭代那么简单,而是一场深刻的变革,清晰的产业蓝图开始显现:始于DeepSeek R1的开源突破,终于Manus的数十亿美元收购,验证了Agent商业化的巨大潜力。 2025年,AI不再是实验室中的抽象概念,而是逐步嵌入日常生产生活,以更加务实的姿态和广泛的应用场景,真正走向了社会的主流。从年初DeepSeek R1的开源发布到年末Manus的天价收购,这两件大事为2025年的AI发展定下了基调:开源与闭源的博弈,技术与商业的融合,模型与应用的深度对接,无疑为AI的未来铺设了一条发展道路。技术突破和产业落地不断交织,AI的角色正在悄然发生深刻的转变——从“辅助工具”走向了“自主执行者”。 文章目录

By Ne0inhk
最新版 Kimi K2.5 进阶实战全攻略:从开源部署到 Agent 集群搭建(视频理解 + 多模态开发 + 高并发调优)

最新版 Kimi K2.5 进阶实战全攻略:从开源部署到 Agent 集群搭建(视频理解 + 多模态开发 + 高并发调优)

1 技术背景与核心架构原理 1.1 技术定位与版本说明 Kimi K2.5 是月之暗面于2026年初发布的开源多模态大语言模型,聚焦长上下文理解、原生多模态交互、Agent 原生支持三大核心能力,针对工业级落地场景完成了全链路优化。本次实战覆盖的开源版本包括: * kimi-k2.5-chat-70b:基础对话版,支持2000K token 上下文窗口,原生适配工具调用 * kimi-k2.5-multimodal-70b:多模态完整版,新增图像、长视频时序理解能力,支持最长10小时连续视频输入 * kimi-k2.5-agent-70b:Agent 优化版,强化多轮工具链执行、分布式状态同步能力,适配集群化部署 * 量化衍生版本:AWQ 4bit/8bit、FP8 量化版,适配低显存硬件环境,精度损失控制在1%以内 1.2 核心架构与技术亮点 1.2.1

By Ne0inhk
一文读懂VR/AR/MR:小白也能分清的虚实交互技术

一文读懂VR/AR/MR:小白也能分清的虚实交互技术

目录 * 前言 * 一、逐个击破 —— 三种技术的 “大白话” 解读 * 1.1 VR(虚拟现实):钻进 “虚拟世界” 不出来 * 1.2 AR(增强现实):给 “现实世界” 加层 “滤镜” * 1.3 MR(混合现实):在 “现实里” 玩 “虚拟物件” * 二、核心区别大对比 —— 一张表 + 一张图看懂 * 2.1 对比表格 * 2.2 可视化对比图(核心区别一目了然) * 三、避坑指南 —— 小白最容易混淆的 2 个误区 * 3.1 误区 1:

By Ne0inhk
开源AI编程工具对决:Superpowers技能库与OpenSpec规范驱动,谁更胜一筹?

开源AI编程工具对决:Superpowers技能库与OpenSpec规范驱动,谁更胜一筹?

文章概要 在AI辅助编程领域,Obra/superpowers库与Fission-AI/OpenSpec库代表了两种截然不同的技术路径。前者致力于构建可复用的AI编程技能库,后者则倡导以规范(Spec)为核心的驱动开发模式。本文将深入对比两者在核心理念、工作流程及适用场景上的核心差异,探讨它们如何分别解决AI开发中的效率与一致性难题,并分析在项目演进中应如何取舍。 前几天在咖啡店,我无意中听到邻桌两位程序员在激烈争论。一位坚持说:“AI编程助手最大的价值就是帮我快速写出新代码,我需要的是更多‘技能’。”另一位则反驳:“不对,AI最该解决的是代码一致性,我们团队现在最缺的是‘规范’。”这让我立刻想到了最近在GitHub上观察到的两个项目:Obra的superpowers技能库和Fission-AI的OpenSpec规范驱动框架。它们恰好代表了这两种截然不同的思路。 我打开superpowers的仓库,第一印象是它像一个为AI助手精心打造的“瑞士军刀”工具箱。它的核心理念非常直接:将常见的、复杂的编程任务封装成一个个可复用的“技能”(Skill)。这就像给AI安装了一个插件商店,当需要

By Ne0inhk