学习grpc

news2024/9/21 14:46:32

Grpc简介:

 gRPC是一个高性能、通用的开源RPC框架,其由Google主要面向移动应用开发并基于HTTP/2协议标准而设计,基于ProtoBuf(Protocol Buffers)序列化协议开发,且支持众多开发语言,能够基于语言自动生成客户端和服务端功能库。且支持java、C++、C#等众多开发语言。

特点:

  1. 通信协议基于标准的 HTTP/2 设计,支持双向流、消息头压缩、单 TCP 的多路复用、服务端推送等特性,这些特性使得 gRPC 在移动端设备上更加省电和节省网络流量;
  2. 语言中立,支持多种语言

编译Grpc:

使用grpc

.proto

.proto 文件用来定义客户端和服务端的服务接口消息字段格式。

syntax = "proto3";   //定义了使用 proto3 的语法

option java_package = "ex.grpc";

package mathtest;   //表示定义消息的包名,对于 C++ 程序,消息类将会被包装在对应的命名空间中

// Defines the service 定义在 RPC 调用中的服务接口,sendRequest 为服务接口,MathRequest为输入参数,MathReply为返回值,MathTest 为服务类,服务端必须继承于它。

service MathTest {

    // Function invoked to send the request

    rpc sendRequest (MathRequest) returns (MathReply) {}

}

// The request message containing requested numbers,字段后面的数字并不表示该字段的值,只是 proto 程序用来生成相关源代码使用

message MathRequest {

    int32 a = 1;

    int32 b = 2;

}

// The response message containing response

message MathReply {

    int32 result = 1;

}

hello.proto文件通过执行命令会生成hello.grpc.pb.cc、hello.grpc.pb.h、hello.pb.cc和hello.pb.h。服务端和客户端就是通过引用这些文件编写代码

配置环境变量

把protoc.exe所在的路径添加到环境变量。打开cmd,输入protoc,回车,可看到是否配置成功。

执行cmd命令

打开cmd, 使用cd命令进入到hello.proto文件所在的目录。

执行protoc.exe ./helloworld.proto --cpp_out=./

会生成hello.pb.h和hello.pb.cc文件

protoc.exe ./hello.proto--plugin=protoc-gen-grpc=E:/work/code/vate_fs/GrpcDemo/grpc/bin/grpc_cpp_plugin.exe --grpc_out=./

会生成hello.grpc.pb.h和hello.grpc.pb.cc文件

需要找到grpc_cpp_plugin.exe 所在的目录

 

 延伸:关键字
Repeated

Repeated是protobuf中的一种限定修饰符,从字面意思看有“重复”的意思,实际上它就是用来指定某一个字段可以存放同一个类型的多个数据,相当于C++中的vector或者Java中的List

message Person {

  required int32 age = 1;

  required  string name = 2;

}

message Family {

  repeated Person person = 1;

}

Family family;

    Person* person;

     //  添加一个家庭成员,John

    person = family.add_person();

    person->set_age(25);

    person->set_name("John");

     //  添加一个家庭成员,Lucy

    person = family.add_person();

    person->set_age(23);

    person->set_name("Lucy");

     //  添加一个家庭成员,Tony

    person = family.add_person();

    person->set_age(2);

    person->set_name("Tony");

     //  显示所有家庭成员

     int size = family.person_size();

    cout << "这个家庭有 " << size << " 个成员,如下:" << endl;

     for( int i=0; i<size; i++)

    {

        Person psn = family.person(i);

        cout << i+1 << ". " << psn.name() << ", 年龄 " << psn.age() << endl;

    }

required

required必须的意思,数据发送方和接收方都必须处理这个字段

optional

字面意思是可选的意思,具体protobuf里面怎么处理这个字段呢,就是protobuf处理的时候另外加了一个bool的变量,用来标记这个optional字段是否有值,发送方在发送的时候,如果这个字段有值,那么就给bool变量标记为true,否则就标记为false,接收方在收到这个字段的同时,也会收到发送方同时发送的bool变量,拿着bool变量就知道这个字段是否有值了,这就是option的意思。

服务端

配置grpc的头文件和依赖库

在vs中,你可以用链接器选择 *.lib来选择目录下所有的静态库.

具体为:在VS项目工程的“属性>配置属性>链接器>命令行>其他选项”中,设置"[lib目录]\*.lib "即可在工程中一次性引入全部lib。

qt无法批量导入一定要把grpc依赖包里的近50个静态库一个一个添加进来

注意事项:把zlibd.dll放到输出可执行程序路径下

创建继承于服务类的子类
重写虚函数的方式,实现服务接口。
注册服务、创建开始服务。
#include <string>
#include <grpcpp/grpcpp.h>
#include "mathtest.grpc.pb.h"

using grpc::Server;
using grpc::ServerBuilder;
using grpc::ServerContext;
using grpc::Status;

using mathtest::MathTest;
using mathtest::MathRequest;
using mathtest::MathReply;

class MathServiceImplementation final : public MathTest::Service {
    Status sendRequest(
            ServerContext* context,
            const MathRequest* request,
            MathReply* reply
    ) override {
        int a = request->a();
        int b = request->b();
        reply->set_result(a * b);
        return Status::OK;
    }
};

void Run() {
    std::string address("0.0.0.0:5000");
    MathServiceImplementation service;
    ServerBuilder builder;
    builder.AddListeningPort(address, grpc::InsecureServerCredentials());
    builder.RegisterService(&service);

    std::unique_ptr<Server> server(builder.BuildAndStart());
    std::cout << "Server listening on port: " << address << std::endl;
    server->Wait();
}
int main(int argc, char** argv) {
    Run();
    return 0;
}

客户端

配置grpc的头文件和依赖库,和服务端一样

客户端封装成一个自定义类,定义一个独占智能指针std::unique_ptr<MathTest::Stub> stub_;
通过私有成员变量 stub_ 向服务端发送请求消息并接收返回结果。
初始化自定义类对象,通过地址创建实例化stub_对象。
#include <string>
#include <grpcpp/grpcpp.h>
#include "mathtest.grpc.pb.h"

using grpc::Channel;
using grpc::ClientContext;
using grpc::Status;

using mathtest::MathTest;
using mathtest::MathRequest;
using mathtest::MathReply;

class MathTestClient {
public:
    MathTestClient(std::shared_ptr<Channel> channel) : stub_(MathTest::NewStub(channel)) {}

    int sendRequest(int a, int b) {
        MathRequest request;

        request.set_a(a);
        request.set_b(b);

        MathReply reply;

        ClientContext context;

        Status status = stub_->sendRequest(&context, request, &reply);

        if(status.ok()){
            return reply.result();
        } else {
            std::cout << status.error_code() << ": " << status.error_message() << std::endl;
            return -1;
        }
    }

private:
    std::unique_ptr<MathTest::Stub> stub_;
};

void Run() {
    std::string address("0.0.0.0:5000");
    MathTestClient client(
            grpc::CreateChannel(
                    address,
                    grpc::InsecureChannelCredentials()
            )
    );

    int response;

    int a = 5;
    int b = 10;

    response = client.sendRequest(a, b);
    std::cout << "Answer received: " << a << " * " << b << " = " << response << std::endl;
}

int main(int argc, char* argv[]){
    Run();

    return 0;
}

protobuf对简单数据的赋值,简单数据直接采用set_xx()即可该xx为proto文件的定义消息上的变量

//在proto定义的消息

message Project{

uint32 Type=1;//类型

string Path=2;//路径

}

Project request;

request.set_type(Type);

request.set_path(Path.toStdString());

对应获取变量为直接是变量作为函数

string  path = request->path();

Uint32 type = request->type();

protobuf 中的嵌套消息的使用主要对set_allocated_mutable_的使用

1 使用set_allocated_,赋值的对象需要new出来,不能用局部的,这里保存的是对象的指针。

2 使用mutable_,赋值时候,可以使用局部变量,因为在调用的时,内部做了new操作。

message ErrorCode {

string message = 1;        //错误信息

string note = 2;           //注释

uint32 code = 3;           //错误码

}

message ProjectRet{

ErrorCode errorCode=1;//错误码

string Value=2;//值

}

test_lib::ProjectRet *response;

    std::string hashvalue = “asa”;

response->set_hashvalue(hashvalue);

test_lib::ErrorCode* errorcode = new test_lib::ErrorCode;

    errorcode->set_note("Project");    

    errorcode->set_code(0);

    errorcode->set_message("OK");

response->set_allocated_errorcode(errorcode);

grpc有四种交互模式

https://blog.csdn.net/Fallinlove520/article/details/121989585?spm=1001.2014.3001.5506

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/729424.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

软负载Nginx详细配置及使用案例

Nginx使用与配置 什么是nginx Nginx 是一个高性能的HTTP和反向代理服务&#xff0c;也是一个IMAP/POP3/SMTP服务。 处理响应请求很快高并发连接低的内存消耗具有很高的可靠性高扩展性热部署 master 管理进程与 worker 工作进程的分离设计&#xff0c;使得 Nginx 具有热部署的…

Quartz表达式在线生成器

Quartz Cron表达式生成器 - devTest.run Quartz是一款高效的定时任务调度框架&#xff0c;由于其稳定性&#xff0c;高可用性和灵活性&#xff0c;Quartz已成为Java企业级开发中应用最为广泛的定时任务调度框架之一。 Quartz的主要特点包括&#xff1a;可配置的作业触发器&…

学C的第二十五天【指针的进阶】

相关代码gitee自取&#xff1a;C语言学习日记: 加油努力 (gitee.com) 接上期&#xff1a; 学C的第二十四天【练习&#xff1a;1. 打印菱形&#xff1b;2. 打印自幂数&#xff1b;3. 求Snaaa..n项之和&#xff1b;4. 喝汽水问题&#xff1b;5. 调整数组使奇数位于偶数前面&…

第三章——处理数据

面向对象编程&#xff08;OOP&#xff09;的本质是设计并扩展自己的数据类型。设计自己的数据类型就是让类型与数据匹配。在创建自己的类型之前必须先了解C内置的类型。 内置的C类型分为两组&#xff1a;基本类型和复合类型 简单变量 程序通常都需要存储信息&#xff0c;为把…

git commit history导出

git log --after"2022-1-1" --dateshort --prettyformat:"%H","%an","%ae","%ad","%s" --shortstat --no-merges再简洁一点 git log --after"2022-4-1" --dateshort --prettyformat:%H,%an,%ae,%ad,%…

Network Neuroscience:整个生命周期的功能连接体指纹

导读 随着年龄的增长&#xff0c;人脑功能结构发生了系统性的变化。然而&#xff0c;功能连接(FC)作为一种检测独特“连接体指纹”的强大特征&#xff0c;使个体能够在同龄人中被识别出来。虽然已在年轻人样本中观察到这种指纹&#xff0c;但该方法在整个生命周期内的可靠性尚…

ACL 2023|大模型时代,自然语言领域还有什么学术增长点?

国际计算语言学年会&#xff08;Annual Meeting of the Association for Computational Linguistics&#xff0c;简称 ACL&#xff09;是自然语言处理&#xff08;NLP&#xff09;领域的顶级国际会议&#xff0c;ACL 2023 将于2023年7月9-14日在加拿大多伦多举行。随着人工智能…

电脑高手的选择:为何只需一款杀毒软件?

对于电脑高手来说&#xff0c;保护计算机免受恶意软件和病毒的侵害至关重要。然而&#xff0c;有些人可能认为安装多个杀毒软件能够提供更优质的防护能力。但事实上&#xff0c;电脑高手通常只选择安装一款杀毒软件&#xff0c;这其中包含着一定的原因和考虑。本文将探讨为什么…

Java版本企业电子招投标采购系统源码功能模块功能描述+数字化采购管理 采购招投标

功能模块&#xff1a; 待办消息&#xff0c;招标公告&#xff0c;中标公告&#xff0c;信息发布 描述&#xff1a; 全过程数字化采购管理&#xff0c;打造从供应商管理到采购招投标、采购合同、采购执行的全过程数字化管理。通供应商门户具备内外协同的能力&#xff0c;为外部…

基于Python+MySQL所写的医院管理系统

点击以下链接获取源码资源&#xff1a; https://download.csdn.net/download/qq_64505944/87985429?spm1001.2014.3001.5503 目录 摘要 I 1 需求分析 1 1.1 任务描述 1 1.2 需求分析的过程 1 1.3 业务需求 2 1.4 功能描述 2 2 总体设计 3 2.1 系统开发环境 3 2.2 系统功能流…

【云原生】Pod 的生命周期

Pod 的生命周期 本文讲解的是 Kubernetes 中 Pod 的生命周期&#xff0c;包括生命周期的不同阶段、存活和就绪探针、重启策略等。 Pod phase Pod 的 status 字段是一个 PodStatus 对象&#xff0c;PodStatus中有一个 phase 字段。 Pod 的相位&#xff08;phase&#xff09;…

DOM事件机制(事件流、事件委托、事件类型)以及BOM

HTML DOM 允许 JavaScript 对 HTML 事件作出反应。JavaScript 能够在事件发生时执行&#xff0c;比如当用户点击某个 HTML 元素时。 JavaScript与HTML之间的交互是通过事件实现的。事件就是文档或浏览器窗口中发生的一些特定的交互瞬间。 虽然 ECMAScript 把浏览器对象模型&…

【面试题28】什么是PHP-FPM?它与PHP和Nginx有什么关系

文章目录 一、前言二、什么是PHP-FPM&#xff1f;三、PHP-FPM的生命周期3.1 启动阶段3.2 初始化阶段3.3 请求处理阶段3.4 关闭阶段 四、PHP-FPM与PHP的关系五、PHP-FPM与Nginx的通信方式六、总结 一、前言 本文已收录于PHP全栈系列专栏&#xff1a;PHP面试专区。 计划将全覆盖P…

【视觉SLAM入门】2.旋转--李群与李代数

"川泽纳污" 0. 一个例子1. 群和李群2. 李代数2.1 推导和性质2.2 s o ( 3 ) \mathscr{so(3)} so(3) 和 s e ( 3 ) \mathscr{se(3)} se(3)2.3 计算李代数的幂 e x p ( ϕ \;exp(\phi exp(ϕ^ ) ) )2.4 李代数乘法2.5 从李代数乘法到导数&#xff1a;2.5.1 直接求导2.…

100天精通Golang(基础入门篇)——第14天:深入解析Go语言函数->从概念到实践,助您精通基础知识!(基础)

&#x1f337; 博主 libin9iOak带您 Go to Golang Language.✨ &#x1f984; 个人主页——libin9iOak的博客&#x1f390; &#x1f433; 《面试题大全》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &#x1f30a; 《I…

第11章:C语言数据结构与算法初阶之排序

系列文章目录 文章目录 系列文章目录前言排序的概念及其运用排序的概念常见的排序算法 常见排序算法的实现1.直接插入排序2. 希尔排序&#xff08;缩小增量排序&#xff09;3. 直接选择排序4. 堆排序5. 冒泡排序6. 快速排序将区间按照基准值划分为左右两半部分的常见方式&#…

使用selenium爬取猫眼电影榜单数据

文章目录 前言导入所需的库&#xff1a;设置ChromeDriver的路径&#xff0c;并创建一个Chrome浏览器实例&#xff1a;打开目标网页&#xff0c;这里以猫眼电影榜单页面为例&#xff1a;使用XPath定位电影信息。通过查看网页源代码&#xff0c;发现电影信息所在的<dd>标签…

深度学习之目标检测Faster RCNN模型算法流程详解说明(超详细理论篇)

1.Faster RCNN论文背景 2. Faster-RCNN算法流程 &#xff08;1&#xff09;Fast-RCNN算法流程 &#xff08;2&#xff09;特征提取conv layers &#xff08;3&#xff09;Region Proposal Networks(RPN) &#xff08;4&#xff09;ROI Pooling作用 &#xff08;5&#xff09;Cl…

Spring定时器调度实现的原理

1、使用Spring定时器任务实现 package com.suyun.modules.vehicle.timetask;import com.alibaba.schedulerx.worker.domain.JobContext; import com.alibaba.schedulerx.worker.processor.JavaProcessor; import com.alibaba.schedulerx.worker.processor.ProcessResult; impo…