学习【gRPC C++简单示例及代码】

2023-05-16

文章目录

  • 0. 启动程序
  • 1. 未作修改部分
    • 1.1 demo.proto
  • 2. 添加注释部分
    • 2.1 server.cc
    • 2.2 client.cc
  • 3. 重点修改部分
    • 3.1 CMakeLists.txt原始代码
    • 3.2 CMakeLists.txt精简修改代码

【gRPC C++简单示例及代码】原文链接
已能够进行初步修改

新建fyo文件夹,在fyo中新建build、include文件夹

进入build文件夹,输入cmake ..make -j,实现了链接中下列代码的功能:

protoc --grpc_out=. --plugin=protoc-gen-grpc=`which grpc_cpp_plugin` demo.proto
protoc --cpp_out=. demo.proto

0. 启动程序

终端1

./demoServer

终端2

./demoClient

1. 未作修改部分

1.1 demo.proto

syntax = "proto3";

package ZYF;
service YServer {
    rpc GetNum(Num) returns (Res) {}
    rpc GetVec(stream Vec)  returns (stream Vec) {}
}

message Num {
    int32 x = 1;
}

message Res {
    int32 y = 1;
}

message Vec {
    repeated int32 v = 1;
}

2. 添加注释部分

2.1 server.cc

#include <iostream>
#include <string>
#include <grpcpp/grpcpp.h>
#include "demo.grpc.pb.h"

class DemoServiceImpl final : public ZYF::YServer::Service {
    // Simple request and response
    grpc::Status GetNum(grpc::ServerContext* context, const ZYF::Num* req, ZYF::Res* res) override {
        std::cout << "Req get:" << req->x() << std::endl;               // fyo: 注意到此处的形式是'req->x()',若改成'req.x()'会报错
        res->set_y(req->x() + 1);                                       // fyo: 此处根据'req->x()'的值,利用'set_y()'对y进行赋值
        																// fyo: 然而set_y()尚未定义,对此作何解释?
        return grpc::Status::OK;                                        // fyo: 返回个啥?
    }
    // Based on stream 
    grpc::Status GetVec(grpc::ServerContext* context, grpc::ServerReaderWriter<ZYF::Vec, ZYF::Vec>* stream) override {
        ZYF::Vec req;
        while (stream->Read(&req)) {                                    // fyo: 怎么就得到循环5次?而且这里的req不是从外面传进来的,而是内部定义的?
            std::cout << "[stream]: Received message!" << std::endl;    // fyo: 
            auto vec = req.v();                                         // fyo: 注意到此处的形式是'req.v()'
            for (auto it = vec.begin(); it != vec.end(); it++) {        // fyo: 怎么就能够得到vec的长度为10???
                (*it)++;
            }
            stream->Write(req);                                         // fyo: 在这5次循环里面,把什么作为req写到stream里面?
                                                                        // fyo: 从req到vec,最后又用req,闹着玩??
        }
        return grpc::Status::OK;
    }
};

void RunServer() {
    std::string serverAddr("0.0.0.0:50051");                                    // fyo: 确定地址端口?
    DemoServiceImpl service;                                                    // fyo: 基于上面定义的DemoServiceImpl类进行实例化?但是暂不调用其内部的函数
    grpc::ServerBuilder builder;                                                // fyo: 创建builder
    builder.AddListeningPort(serverAddr, grpc::InsecureServerCredentials());    // fyo: 调用builder函数
    builder.RegisterService(&service);                                          // fyo: 调用builder函数
    std::unique_ptr<grpc::Server> server(builder.BuildAndStart());              // fyo: 于此处创建server?
    std::cout << "Server listening on:" << serverAddr << std::endl;             // fyo: 打印端口地址
    server->Wait();     // fyo: 在server持续等待的过程中,一经启动,就会触发DemoServiceImpl()函数,可以重复无数遍!
    					// fyo: wait过程中,什么是触发条件?为什么触发后仍然会恢复到wait状态,而不是直接结束?
}

int main(int argc, char** argv) {   // fyo: main函数
    RunServer();                    // fyo: 调用RunServer函数
    return 0;
}

2.2 client.cc

#include <iostream>
#include <string>
#include <grpcpp/grpcpp.h>
#include "demo.grpc.pb.h"

class Client {
public:
    Client(std::shared_ptr<grpc::Channel> channel):stub_(ZYF::YServer::NewStub(channel)){}
    int SendRequest() {
        ZYF::Num req;       // fyo: 'ZYF::Num'指的是proto中定义的Num?以Num为准对req进行实例化?
        req.set_x(3);       // fyo: 此处的'set_x'尚未经定义呀?咋就直接给定义上数值3了?
                            // fyo: 且server.cc文件中是以'req->x()'的形式方可print,与此处'req.set_x(3)'形式不同
        ZYF::Res res;       // fyo: 'ZYF::Res'指的是proto中定义的Res?
                            // fyo: 以Res为准对res进行实例化?
        grpc::ClientContext context;                                    // fyo: 利用grpc::ClientContext对context进行实例化*1
        grpc::Status status = stub_->GetNum(&context, req, &res);       // fyo: 调用server.cc文件中的DemoServiceImpl类中的GetNum?
                                                                        // fyo: 还是调用server.cc文件中的grpc::Status包含的GetNum?

        if (!status.ok()) {
            return -1;
        }
        return res.y();     // fyo: 最终值取4,server.cc文件中的GetNum中进行了一个未经定义的'res->set_y(req->x() + 1)',应当是该处将res.y()定义为3+1=4
    }
    // Send requests based on gRPC stream
    void SendRequestStream() {
        grpc::ClientContext context;                                        // fyo: 利用grpc::ClientContext对context进行实例化*2,有无必要再来一次?
        std::shared_ptr<grpc::ClientReaderWriter<ZYF::Vec, ZYF::Vec>> stream(stub_->GetVec(&context));  // fyo: 调用server.cc文件中的GetVec?
        for (int i = 0; i < 5; ++i) {
            ZYF::Vec req;                                                   // fyo: 5次循环中,每次都以Vec定义一遍req 
            for (int j = 0; j < 10; ++j) {                                  // fyo: 遍历10次,j依次+1
                req.add_v(j);                                               // fyo: 把j的值赋给req,覆盖掉之前的值还是添加新值?另外,此处的'add_v'同上面的'set_x'一样未经定义?
                                                                            // fyo: 难道实际上是把值赋给'ZYF::Vec'???
                                                                            // fyo: 此处'add_v'不同于前面的'set_x'和'set_y'
            }
            if (!stream->Write(req)) {                                      // fyo: 是何用意?
                std::cout << "The stream has been closed!" << std::endl;    // fyo: 打印此条,证明程序运行中断
                break;
            }
            std::cout << "Send a message based on stream!" << std::endl;    // fyo: 打印此条,证明越过前几行代码中的条件,顺利执行后续代码
        }
        stream->WritesDone();                                               // fyo: 是何用意?要传的数据写完了?谁写的?往哪里写的?

        ZYF::Vec res;                                                       // fyo: 与上文中定义req不同,此处以Vec定义res
        while (stream->Read(&res)) {                                        // fyo: 当res里面尚存未读的内容即为真?一共循环5次?怎么会循环5次?
                                                                            // fyo: 难道以res同名同姓一共有5个?的源自上文代码中对'ZYF::Vec req'的“循环定义”?
            std::cout << "Receive a reply!" << std::endl;
            auto reply = res.v();                                           // fyo: 将res中的v()值赋给reply
            for (auto it = reply.begin(); it != reply.end(); it++) {        // fyo: 遍历reply的所有值
                std::cout << (*it) << " " << std::endl;
            }
            std::cout << std::endl;
        }
        stream->Finish();                                                   // fyo: 是何用意?数据传完了?谁传的?往哪里传的?
                                                                            // fyo: 通篇也没有明说要往stream里面写数据啊
    }
private:
    std::unique_ptr<ZYF::YServer::Stub> stub_;
};

int main(int argc, char** argv) {
    Client client(grpc::CreateChannel("localhost:50051", grpc::InsecureChannelCredentials()));
    std::cout << "Got Response:" << client.SendRequest() << std::endl;      // fyo: print值为4,上文中已做解释
    client.SendRequestStream();
    return 0;
}

3. 重点修改部分

3.1 CMakeLists.txt原始代码

cmake_minimum_required(VERSION 3.5.1)

project(DemoGrpc C CXX)
include(./common.cmake)

set(proto_srcs "${CMAKE_CURRENT_BINARY_DIR}/../demo.pb.cc")
set(proto_hdrs "${CMAKE_CURRENT_BINARY_DIR}/../demo.pb.h")
set(grpc_srcs "${CMAKE_CURRENT_BINARY_DIR}/../demo.grpc.pb.cc")
set(grpc_hdrs "${CMAKE_CURRENT_BINARY_DIR}/../demo.grpc.pb.h")

include_directories("${CMAKE_CURRENT_BINARY_DIR}")

add_library(grpc_proto ${proto_srcs} ${proto_hdrs} ${grpc_srcs} ${grpc_hdrs})

target_link_libraries(grpc_proto ${_REFLECTION} ${_GRPC_GRPCPP} ${_PROTOBUF_LIBPROTOBUF})

add_executable(demoServer "server.cc")
add_executable(demoClient "client.cc")
target_link_libraries(demoServer grpc_proto ${_REFLECTION} ${_GRPC_GRPCPP} ${_PROTOBUF_LIBPROTOBUF})
target_link_libraries(demoClient grpc_proto ${_REFLECTION} ${_GRPC_GRPCPP} ${_PROTOBUF_LIBPROTOBUF})

3.2 CMakeLists.txt精简修改代码

cmake_minimum_required(VERSION 3.2)

project(xxxxx)
include(./common.cmake)

# Generated sources
set(coordinate_proto_srcs "${CMAKE_BINARY_DIR}/../include/demo.pb.cc")
set(coordinate_proto_hdrs "${CMAKE_BINARY_DIR}/../include/demo.pb.h")
set(coordinate_grpc_srcs "${CMAKE_BINARY_DIR}/../include/demo.grpc.pb.cc")
set(coordinate_grpc_hdrs "${CMAKE_BINARY_DIR}/../include/demo.grpc.pb.h")

include_directories(include)

# rg_grpc_proto
add_library(coordinate_grpc_proto ${coordinate_grpc_srcs} ${coordinate_grpc_hdrs} ${coordinate_proto_srcs} {coordinate_proto_hdrs})
target_link_libraries(coordinate_grpc_proto ${_REFLECTION} ${_GRPC_GRPCPP} ${_PROTOBUF_LIBPROTOBUF})

add_executable(demoServer "server.cc")
add_executable(demoClient "client.cc")

target_link_libraries(demoServer coordinate_grpc_proto ${_REFLECTION} ${_GRPC_GRPCPP} ${_PROTOBUF_LIBPROTOBUF})
target_link_libraries(demoClient coordinate_grpc_proto ${_REFLECTION} ${_GRPC_GRPCPP} ${_PROTOBUF_LIBPROTOBUF})

get_filename_component(coordinate_proto "./demo.proto" ABSOLUTE)
get_filename_component(coordinate_proto_path "${coordinate_proto}" PATH)

# 以下为较原代码新增加部分

add_custom_command(
      OUTPUT "${coordinate_proto_srcs}" "${coordinate_proto_hdrs}" "${coordinate_grpc_srcs}" "${coordinate_grpc_hdrs}"
      COMMAND ${_PROTOBUF_PROTOC}
      ARGS --grpc_out "${CMAKE_BINARY_DIR}/../include"
        --cpp_out "${CMAKE_BINARY_DIR}/../include"
        -I "${coordinate_proto_path}"
        --plugin=protoc-gen-grpc="${_GRPC_CPP_PLUGIN_EXECUTABLE}"
        "${coordinate_proto}"
      DEPENDS "${coordinate_proto}")
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

学习【gRPC C++简单示例及代码】 的相关文章

  • 视觉SLAM

    01 章国锋 xff1a 视觉SLAM最新观点分享 讲座视觉SLAM在AR应用上的关键性问题探讨 xff0c 内含PPT与答疑 直播回放 中国知网回放地址 http k cnki net CInfo Index 6370 B站回放地址 ht
  • python中zmq的基础三种模式

    ZMQ 的三个基本模型 ZMQ 提供了三个基本的通信模型 xff0c 分别是 Request Reply xff0c Publisher Subscriber xff0c Parallel Pipeline 请求应答模式 xff08 Req
  • AI安全01 人工智能的安全性

    前言 提问 xff1a GPT老师 xff0c 我想写一篇阅读量高一点的信息安全博文 xff0c 您可以推荐写作主题吗 xff1f GPT老师 xff1a 人工智能与信息安全 写在前面 xff1a 1 笔者相关知识存储很少 xff0c 这篇
  • 关于linux下进程和线程优先级的一些总结

    1 进程 1 1 基础 进程优先级值越小 xff0c 优先级越大 xff0c 进程的优先级是PRI值不是Nice值 xff0c 普通进程优先级可以通过Nice值调整 xff0c 实时进程不行 Linux的进程分普通进程 xff08 非实时进
  • 采用x11转发实现远程docker容器的图形化显示

    本地ubuntu主机 windows下有多种图形化工具可以用 xff0c 具体可参考wsl2图形化显示 1 主机安装x11 utils 2 xhost 43 进行授权 远程docker 1 安装ssh并修改 etc ssh sshd con
  • JavaScript类型

    为什么有的编程规范要求用 void 0 代替 undefined xff1f 字符串有最大长度吗 xff1f 0 1 43 0 2 不是等于 0 3 么 xff1f 为什么 JavaScript 里不是这样的 xff1f ES6 新加入的
  • ubuntu 内网搭建服务器的一些配置,完美解决https、http、curl、wget、yum 无法访问的问题

    1 一些需求可能要 继承IP 网关才能连接到外网 xff0c linux 不知道在如何配置可以来看看 http proxy 61 http 192 254 1 10 8088 ftp proxy 61 http 192 254 1 10 8
  • 堆、栈、队列、各种变量(静态、动态、全局、局部)的区别和联系

    堆栈都是一种数据项按序排列的数据结构 xff0c 只能在一端 称为栈顶 top 对数据项进行插入和删除 堆 heap 堆 xff08 操作系统 xff09 xff1a 一般由程序员分配释放 xff0c 若程序员不释放 xff0c 程序结束时
  • 论文中baseline是什么意思?

    问题1 xff1a benchmark和baseline的区别 xff1f 在计算机视觉论文中benchmark和baseline的区别 问题2 xff1a 经常在论文中看见baseline但是不明白里面是在写的什么 xff1f 其实就是你
  • linux 执行命令提示无权限排查思路

    问题描述 在root用户下su到普通用户出现权限问题 root 64 hehe su zh su warning cannot change directory to home zh Permission denied su failed
  • C#应用程序界面开发进阶——高级窗体控件(2)——列表视图控件(最后一个代码不行)

    列表视图 xff08 ListView xff09 控件是Windows列表视图控件 xff0c 用于显示带图标的项的列表 创建列表视图控件 为列表视图控件添加项有以下两种方法 xff08 1 xff09 直接单击控件上方的小箭头 xff0
  • ubuntu16.04LTS更换阿里源

    sudo gedit etc apt sources list 替换 xff1a 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 deb cdrom Ubuntu 16 04 LTS Xenial
  • Nginx 配置问题 server directive is not allowed here in /etc/nginx/nginx.conf:69

    前沿 今天在其他服务器上重新配置 nginx conf 文件 xff0c 配置结束启动 nginx 发现遇到了这样一个错误 xff0c 我擦 我配置文件都是从上个服务器上 复制粘贴过来的 xff0c 怎么会遇到这个问题呢 xff1f 百思不
  • labelImg ZeroDivisionError: float division by zero 问题定位和解决方案

    一 前沿 labelImg的使用和安装这里不过多讲解 xff0c 网上一堆教程 二 问题以及解决方案 2 1 问题如下 xff1a Traceback span class token punctuation span most recen
  • Linux系统下查看版本信息

    一 前沿 有时候回去查看Linux的版本信息和内核 xff0c 每次可能都需要百度一下 xff0c 今天记录一下 xff0c 方便以后自己看 二 查看Linux内核版本命令 2 1 第一种方式 显示正在运行的内核版本 1 cat proc
  • Centos7下安装 prometheus+grafana

    一 前言 1 什么是 Prometheus xff1f Prometheus是最初在SoundCloud上构建的开源系统监视和警报工具包 自2012年成立以来 xff0c 许多公司和组织都采用了Prometheus xff0c 该项目拥有非
  • Linux ssh:handshake failed:EOF

    一 前沿 1 Notes xff1a 以下操作均在 京东云服务器 2 在配置好免密登陆之后 xff0c 通过ssh登陆的时候间接性的遇见 ssh handshake failed EOF 真是让人恼火 xff0c 所以给总结一下 二 解决步
  • prometheus 文件配置小技巧优化

    一 前言 很久没看过监控 xff0c 直到公司机器越来越多 xff0c 项目越来越多 xff0c prometheus yml 文件一直在增加显得很杂乱无章 xff0c 这里优化了根据项目文件来改配置文件 二 优化 1 prometheus
  • prometheus通过process-exporter监控进程并实现企业报警

    一 前沿 通过上级篇文章我们已经对 Prometheus监控服务器基础资源做了记录 xff0c 这节课主要记录一下监控服务器上的进程 二 实现步骤 Prometheus机器IPprocess exporter机器IP192 168 1 31
  • python - RSA加密

    什么是RSA xff1f 这里粘贴一些定义 RSA公开密钥密码体制 所谓的公开密钥密码体制就是使用不同的加密密钥与解密密钥 xff0c 是一种 由已知加密密钥推导出解密密钥在计算上是不可行的 密码体制 在公开密钥密码体制中 xff0c 加密

随机推荐

  • scrapy-设置请求头

    当我们大量使用scrapy 请求一个网站的时候我们知道scrapy默认的请求头是 xff1a 可以看到默认的请求头就是scrapy xff0c 这样就很容易导致浏览器封掉的可能 xff0c 这个时候我们就需要给请求加一个请求头来模拟浏览器
  • Android Studio gradle配置

    settings gradle 配置指定路径 module 博主博客 https blog uso6 comhttps blog csdn net dxk539687357 一 正常情况 xff0c 导入本项目的模块只需要使用 includ
  • Windows10 安装 pytesseract 出错 Error opening data file Tesseract-OCR\tessdata/eng.traineddata

    首先表明自己出现的错误 xff1a D BuildFolder tesseract ocr testing gt tesseract dlld exe eurotext tif eurotext span class hljs keywor
  • python--爬取微信公众号

    缘由 相信大家有时候面试的时候会遇到爬取微信公众号的事情 xff0c 终于闲了会参考大佬文章自己也搞了一个微信公众号的爬取简单分享一下 xff0c 莫嫌弃代码low 借鉴知识 博客参考 xff1a https blog csdn net x
  • 物联网操作系统的三大核心流派

    物联网操作系统的三大核心流派 目前 xff0c 市面上的物联网操作系统 基本形成了三大核心流派 1 由传统的嵌入式RTOS发展而来 xff0c 典型代表 xff1a FreeRTOS RT Thread LiteOS uCOS MICO 优
  • “> /dev/null 2>&1“ 含义

    在使用python时 xff0c 有时我们可能会看到这样的代码段 pip install gym pyvirtualdisplay span class token operator gt span span class token ope
  • 认识MEC

    文章目录 一 什么是MEC 二 什么是移动通信系统 三 为什么要有MEC 一 什么是MEC 所谓MEC 从字面上直观理解就能知道 这是一种运用在移动通信系统 Mobile 边缘节点 Edge 并承担大量计算任务 Computer 的玩意儿
  • ROS学习-2 工作空间文件结构和创建功能包

    古月居ROS入门21讲第九个视频 src放功能包的源码和laungh文件 build是编译过程中产生的中间文件 xff0c 二进制文件 install是安装空间 xff0c 放最终编译生成的可执行文件的 xff0c 可以给客户使用的文件 d
  • HC32L系列MCU在KEIL新建工程后在JLINK 下 SW Device下找不到设备的解决方法

    HC32L系列MCU在KEIL新建工程后在JLINK 下 SW Device下找不到设备的解决方法 问题 xff1a 新建工程HC32L的工程 xff0c 通过JLINK连接目标板 xff0c 点击KEIL环境的魔术棒 xff0c 选取JL
  • 漫谈Anchor-based和Anchor-Free

    曾几何时 xff0c Anchor based独霸目标检测这块CV疆域内的肥沃之地 如今 xff0c Anchor Free以其灵活的走位在目标检测中有了一席之地 xff0c 正以星星之火可以燎原之势扩大着自己的声势 Anchor base
  • 【新书推荐】【2020】基于MATLAB和Pixhawk的多轴飞行器设计与控制实践

    本书是斯普林格于2017年出版的 Introduction to Multicopter Design and Control 的姊妹版本 xff0c 旨在通过一个实际的过程帮助读者加深对多轴飞行器设计与控制的理解 As the siste
  • 【新书推荐】【2020】无人机系统设计

    从系统角度全面介绍无人飞机系统的设计和分析 Provides a comprehensive introduction to the design and analysis of unmanned aircraft systems with
  • HDFS使用Kerberos

    转载自 xff1a http www datastart cn tech 2016 06 07 kerberos 1 html 本文尝试记录HDFS各服务配置使用kerberos的过程 xff0c 配置的东西比较多 xff0c 一定会有疏漏
  • 【无人机】【2011.03】无人飞行器的自主飞行研究

    本文为澳大利亚悉尼大学 xff08 作者 xff1a Nicholas R J Lawrance xff09 的博士论文 xff0c 共233页 无人机 xff08 UAV xff09 在一系列工业 科学和国防应用中提供了独特的能力 小型无
  • 【无人机】【2019】无人机巡线路由算法研究

    本文为美国密苏里理工大学 xff08 作者 xff1a YU LI xff09 的硕士论文 xff0c 共79页 随着机器人技术的迅速发展 xff0c 越来越多的公用事业公司使用机器人来执行各种任务 无人机是一种高效的高压输电线路巡检机器人
  • 【电力电子】【2010.09】无人机系统的自适应控制

    四旋翼直升无人机 本文为美国麻省理工学院 xff08 作者 xff1a Zachary Thompson Dydek xff09 的博士学位论文 xff0c 共139页 自适应控制被认为是未来高性能 关键安全系统 xff08 如高超声速飞行
  • 【新书推荐】【2018.11】无人机多传感器导航的非线性卡尔曼滤波

    2018 11 无人机多传感器导航的非线性卡尔曼滤波Nonlinear Kalman Filter for Multi Sensor Navigation of Unmanned Aerial Vehicles xff0c 共254页 如果
  • 【源码】轻松实现四轴飞行器的模拟与控制

    本模型取自题为 Quadcopter Simulation and Control Made Easy 的网络研讨会 xff0c 您可以在这里找到相关视频内容 xff1a https www mathworks com videos qua
  • 【无人机】【2014.08】无人机循环路由

    本文为以色列理工学院 xff08 作者 xff1a Nir Drucker xff09 的硕士论文 xff0c 共65页 许多无人驾驶飞行器 xff08 UAV xff09 针对的国防和民用相关任务涉及在各种时间限制下监测预先确定的一组地面
  • 学习【gRPC C++简单示例及代码】

    文章目录 0 启动程序1 未作修改部分1 1 demo proto 2 添加注释部分2 1 server cc2 2 client cc 3 重点修改部分3 1 CMakeLists txt原始代码3 2 CMakeLists txt精简修