news 2026/7/27 0:33:48

C++ grpc 基础教程学习

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C++ grpc 基础教程学习

前言

本文根据 https://grpc.io/docs/languages/cpp/basics/ 进行 C++ grpc RouteGuide示例学习运行,主要是四种RPC类型的简单使用示例。更多的是学习记录,水平不高,能力有限,错漏之处,还请见谅。欢迎友好讨论。

环境信息

  • 操作系统版本:CentOS 7.6

  • CMake版本:4.2.0

  • Git版本:2.25.0

  • GCC版本:gcc 11.2

  • GLIBCXX 版本:libstdc++.so.6.0.29(伴随gcc11.2安装)

  • as & ld版本: 2.45

相关安装部署教程可以参考https://mp.weixin.qq.com/s/50Tep3mq7wkuCzVtAF-2DA

grpc官方仓库运行流程

编译

参考 https://mp.weixin.qq.com/s/50Tep3mq7wkuCzVtAF-2DA 进行编译grpc之后,执行如下步骤:

  • 在grpc源码文件夹下执行

    • cd examples/cpp/route_guide
  • 运行Cmake指令

    • export MY_INSTALL_DIR=xxxxxxxx # grpc本地安装路径 mkdir -p cmake/build cd cmake/build cmake -DCMAKE_C_COMPILER=/usr/local/gcc-11.2.0/bin/gcc \ # 高版本gcc位置, 如果默认版本满足需求, 则无需指定 -DCMAKE_CXX_COMPILER=/usr/local/gcc-11.2.0/bin/g++ \ # 高版本g++位置, 如果默认版本满足需求, 则无需指定 -DCMAKE_PREFIX_PATH=$MY_INSTALL_DIR ../.. # 执行编译 make
  • 编译完成

运行

  • 在examples/cpp/route_guide/cmake/build文件下运行服务器

    • ./route_guide_server --db_path=../../route_guide_db.json
  • 重新开一个终端,在examples/cpp/route_guide/cmake/build文件夹下运行客户端

    • ./route_guide_client --db_path=../../route_guide_db.json

个人仓库代码运行流程

编译

参考 https://mp.weixin.qq.com/s/50Tep3mq7wkuCzVtAF-2DA 克隆仓库 https://github.com/EarthlyImmortal/blog_code 并配置grpc依赖,然后执行如下操作:

  • 修改 blog_code/route_guide/start_build.sh 中的gcc和g++路径

  • 在blog_code/route_guide目录下执行start_build.sh

    • ./start_build.sh

运行

  • blog_code/route_guide/build/server 文件夹下运行服务器

    • ./server --db_path=../../route_guide_db.json
  • 另起一个终端,在blog_code/route_guide/build/client文件夹下运行客户端

    • ./client --db_path=../../route_guide_db.json

这部分代码完全是copy的grpc官方的示例,只对cmake文件和目录结构做了调整。个人仓库的好处是可以省去编译grpc的时间,直接使用我编译好的库。

下面我将对 route_guide 示例代码进行简单分析。以下分析均使用个人仓库代码测试。

代码简单分析

protobuf定义

文件:route_guide/proto/route_guide.proto

主要是定义了服务和接口名以及要用到的消息结构。

  • 服务和接口名:
    • 类型:service,在这个示例中如service RouteGuide

    • 定义的接口:GetFeature(一元RPC);ListFeatures(服务器流式RPC); RecordRoute(客户端流式rpc); RecordRoute(双向流式 RPC)

    • 生成插件:grpc插件,文件在grpc/bin/grpc_cpp_plugin

    • 生成的文件:route_guide/proto/route_guide.grpc.pb.h;route_guide/proto/route_guide.grpc.pb.cc

  • 消息结构
    • 类型:message,如message Point等

    • 生成插件:无

    • 生成的文件:route_guide/proto/route_guide.pb.h;route_guide/proto/route_guide.pb.cc

暂时不对生成的文件进行分析了,目前对我来说有点复杂,后续再深入学习之后再进行分析。

辅助函数

文件:route_guide/common/helper.h;route_guide/common/helper.cpp

主要是为了从json文件中解析出Feature信息。Feature信息定义如下:

被解析的json文件路径:route_guide/route_guide_db.json。这其实就是一个json形式的Feature信息列表,代表一些城市的E7表示法经纬度信息,可以看message Point的注释。部分数据如下:

客户端和服务器代码简介

这个示例主要是为了展示grpc的四种rpc类型,即一元 RPC(Unary RPC)、服务器流式 RPC(Server streaming RPC)、客户端流式 RPC(Client streaming RPC)、双向流式 RPC(Bidirectional streaming RPC)。因此对代码的分析也分为这四种rpc类型来看。

一元 RPC(Unary RPC)

  • 接口名:GetFeature

  • 协议定义

  • 服务器代码:

  • 客户端代码

  • 输出信息

  • 功能介绍:客户端向服务器请求点的特征信息。客户端传入一个点的信息,获取这个点的特征信息。在客户端测试程序中测试了两个点,从返回信息中可知,这两个点一个存在特征信息(指有名字信息),一个不存在特征信息。

服务器流式 RPC(Server streaming RPC)

  • 接口名:ListFeatures

  • 协议定义

  • 服务器代码

  • 客户端代码

  • 输出信息

  • 功能介绍

    • 这个接口是客户端传给服务器一个矩形区域(用两个点表示),然后服务器返回给客户端在这个矩形区域范围内的所有点。与一元 RPC(Unary RPC)不同的是,服务器并不是将所有的点信息在一个消息包内一次性返回的,而是分多个包流式返回。这一点可以通过抓包来发现。抓包流程可以通过 抓包操作流程 一节得到。
      • ...

客户端流式 RPC(Client streaming RPC)

  • 接口名:RecordRoute

  • 协议定义

  • 服务器代码

  • 客户端代码

  • 输出信息

  • 功能介绍

    • 客户端向服务器发送一定数量的点,服务器计算出一共有几个点,这些点里面还有几个特征点(指有名字信息的点位),依次走过这些点的距离是多少,以及依次获取一共花了多少时间。在示例代码中,客户端在所有点中随机出10个点,依次发给服务器,每次发送一个点随机等0.5到1.5s,作为从一个点到另一个点的时间。最后服务器返回经过了10个点,其中4个特征点,总共经过733376米,花费9s。与一元 RPC(Unary RPC)不同的是。客户端并不是将所有的点信息在一个消息包内一次性发送的,而是分多个包流式发送。这一点可以通过抓包来发现。抓包流程可以通过 抓包操作流程 一节得到。
      • 在客户端发送第一个点位信息之后,客户端和服务器之间还会有几次交互,然后才发送下一个点位信息。这些交互中有些可能是tcp底层的交互,但是有些应该是带信息的业务包。不过暂时先不深究。

      • 上面用到的pb解析工具可以在blog_code/route_guide/python_tool中找到

双向流式 RPC(Bidirectional streaming RPC)

  • 接口名:RouteChat

  • 协议定义

  • 服务器代码

  • 客户端代码

  • 输出信息

  • 功能介绍:客户端向服务器发送点位以及点位上的附加信息,服务器首先遍历当前接收过的所有信息,把属于同一个点位的信息返回给客户端,然后把客户端传过来的信息记录下来。在这个示例中,客户端发送信息是额外起一个线程去做的,连续发送了4条信息,其中前三条信息,因为点位各不相同,所以没有信息返回,而第4条信息因为点位和第一条信息相同,所以服务器会返回第一条信息。如果我们在不停止服务器的情况下,连续两次运行客户端,可以得到如下输出。可以发现,因为第一轮运行的时候,已经在点位(0,0) 写入First和Fourth两条信息,所以在第二轮运行再次向点位(0,0) 发送First信息的时候,对应会有两条信息从服务器返回,其他的依次类推。同样我们可以抓包分析这些信息客户端和服务器均为多次流式发送的,这里不再展开。

抓包操作流程

  • 安装wireshark

    • sudo yum install -y wireshark wireshark-gnome # 这里连图形界面一起安装, 虽然暂时没有用到
  • 使用tcpdump抓包

    • sudo tcpdump -i any -s 0 -w grpc_stream.pcap 'port 50051' # -i any: 监听所有网络接口 # -s 0: 设置快照长度(snaplen)为0,确保捕获每个数据包的完整内容,避免截断 # -w grpc_stream.pcap: 将原始数据包保存到文件,这是后续分析的基础 # port 50051: 过滤器,只捕获与该端口相关的流量,大幅减少干扰
  • 使用tshark分析

    • tshark -r grpc_stream.pcap -V > tmp.txt

说明

鉴于时间和水平原因,有些通讯细节并未深究,比如在流式RPC中客户端和服务器之间应该有一些额外的交互。学习是一个逐渐深入的过程,后续会逐步搞清楚。

参考资料

  • 腾讯元宝-deepseek(https://yuanbao.tencent.com/)和deepseek官方网站(https://www.deepseek.com/)辅助

  • https://grpc.io/docs/languages/cpp/basics/

  • https://mp.weixin.qq.com/s/50Tep3mq7wkuCzVtAF-2DA

欢迎关注公众号:只做人间不老仙

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/21 15:21:03

C语言数据结构-数组实现栈详解

在计算机科学中,栈是一种遵循“后进先出”(LIFO)原则的数据结构。在C语言中,我们可以用数组来构建一个栈。数组为我们提供了一块连续的内存空间。我们定义栈的最大容量为5,这意味着我们的栈最多只能存放5个元素。 #in…

作者头像 李华
网站建设 2026/7/14 18:23:37

Sonic数字人服装更换功能?目前依赖图像预处理

Sonic数字人如何实现服装更换?答案藏在图像预处理中 在虚拟主播24小时不间断直播、短视频工厂批量生产口播内容的今天,数字人早已不再是实验室里的概念玩具。真正让这类技术落地的关键,并非一味追求3D建模的复杂度,而是找到一条“…

作者头像 李华
网站建设 2026/7/20 13:37:39

细品古诗,神交古人

14.《忘川谣》 传说阴间有忘川,饮其水者忘前缘。 我愿此川现人世,洗尽恩怨焕新天。 15.《洛神新赋》 洛水女神今何在?虚拟现实显真身。 凌波微步像素动,回眸一笑迷众生。 16.《精卫石》 精卫衔石填海忙,愚公移山志气…

作者头像 李华
网站建设 2026/7/25 17:52:00

Sonic生成失败报错怎么办?常见错误代码速查表

Sonic生成失败报错怎么办?常见错误代码速查表 在虚拟内容创作爆发的今天,数字人技术正以前所未有的速度渗透进短视频、在线教育、电商直播等场景。一个只需上传一张照片和一段音频,就能自动生成“会说话”的人物视频的工具——Sonic&#xff…

作者头像 李华
网站建设 2026/7/22 13:03:40

以太网交换基础

目标描述以太网的基本概念;区分MAC地址的类型;描述二层交换机的工作流程;描述MAC地址表的构成与形成过程。一、以太网协议介绍1.以太网协议以太网是当今现有局域网采用的最通用的通信协议标准,该标准定义了在局域网中采用的电缆类…

作者头像 李华
网站建设 2026/7/16 10:12:28

Sonic数字人视频SEO优化技巧:提升搜索引擎曝光率

Sonic数字人视频SEO优化技巧:提升搜索引擎曝光率 在短视频流量主导内容分发的今天,企业与创作者正面临一个共同挑战:如何以低成本、高效率持续产出优质视频内容?传统真人出镜模式受限于人力、设备和制作周期,难以满足…

作者头像 李华