学习grpc

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 ./hello.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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值