grpc使用教程

转自:grpc使用教程-CSDN博客

grpc是google开源的rpc框架,默认使用protobuf序列化格式

本文介绍grpc使用的全过程,包括:

1.proto文件设计和编写

2.使用protoc编译器生成代码框架(包含接口定义)

3.根据生成的框架代码自己实现服务端和客户端的逻辑(重写框架中定义的接口)

一、proto文件
我们使用protobuf序列化格式,这个由谷歌设计的协议旨在提供高效的序列化机制,支持高性能服务

设计一个注册和登录的服务
syntax = "proto3";  // protoc版本
package IM.Login;   // 命名空间: 项目名.模块名

// 定义服务类型,关键字:service
service ImLogin {
   rpc Regist(IMRegistReq) returns (IMRegistRes) {}     // 使用rpc关键字 
   rpc Login(IMLoginReq) returns (IMLoginRes) {}        // 与普通函数定义类似,Login是函数名,IMLoginReq是参数,returns是返回值
}

// 定义注册类型,关键字:message
message IMRegistReq{
    string user_name = 1; // 这里变量 user_name = 1 并不是赋值,1表示变量的编号,用于两端互相解析数据,下文同理  
    string password = 2; 
}
// 注册返回
message  IMRegistRes{
    string user_name = 1; 
    uint32 user_id = 2; 
    uint32 result_code = 3; // 返回0的时候注册注册
}
// 登录请求
message IMLoginReq{
    string user_name = 1; 
    string password = 2; 
}
// 登录返回
message  IMLoginRes{
    uint32 user_id = 1; 
    uint32 result_code = 2; 
}

二、使用protoc编译器生成框架代码
编译命令:(如何使用protoc编译,见下文)

protoc --cpp_out=. --grpc_out=. --plugin=protoc-gen-grpc=/usr/local/bin/grpc_cpp_plugin IM.Login.proto

生成C++代码IM.Login.pb.h和IM.Login.pb.cc, IM.Login.grpc.pb.h和IM.Login.grpc.pb.cc

从.proto文件生成了什么?

当用protocol buffer编译器来运行.proto文件时,编译器将生成所选择语言的代码,这些代码可以操作在.proto文件中定义的消息 类型,包括获取、设置字段值,将消息序列化到一个输出流中,以及从一个输入流中解析消息。

1.对C++来说,编译器会为每个.proto文件生成一个.h文件和一个.cc文件,.proto文件中的每一个消息有一个对应的类。

2.对Java来说,编译器为每一个消息类型生成了一个.java文件,以及一个特殊的Builder类(该类是用来创建消息类接口 的)。

3.对Python来说,有点不太一样——Python编译器为.proto文件中的每个消息类型生成一个含有静态描述符的模块,,该模块 与一个元类(metaclass)在运行时(runtime)被用来创建所需的Python数据访问类。

4.对go来说,编译器会位每个消息类型生成了一个.pd.go文件。

5.对于Ruby来说,编译器会为每个消息类型生成了一个.rb文件。

6.javaNano来说,编译器输出类似域java但是没有Builder类

7.对于Objective­C来说,编译器会为每个消息类型生成了一个pbobjc.h文件和pbobjcm文件,.proto文件中的每一个消息有一个 对应的类。

8.对于C#来说,编译器会为每个消息类型生成了一个.cs文件,.proto文件中的每一个消息有一个对应的类。

三、根据生成的框架代码自己实现服务端和客户端的逻辑
这是根据.proto文件生成的代码目录:

我们需要根据这些文件中提供的接口定义,来实现服务端代码的逻辑,有两个步骤

1.实现接口函数

2.根据接口实现业务逻辑

服务端代码
1.实现接口函数
首先创建server.cc文件,定义头文件,开放命名空间:

#include <iostream>
#include <string>

// grpc头文件
#include <grpcpp/ext/proto_server_reflection_plugin.h>
#include <grpcpp/grpcpp.h>
#include <grpcpp/health_check_service_interface.h>

// 包含我们自己proto文件生成的.h
#include "IM.Login.pb.h"
#include "IM.Login.grpc.pb.h"

// 命名空间
// grcp
using grpc::Server;
using grpc::ServerBuilder;
using grpc::ServerContext;
using grpc::Status;
// 自己proto文件的命名空间
using IM::Login::ImLogin;
using IM::Login::IMRegistReq;
using IM::Login::IMRegistRes;
using IM::Login::IMLoginReq;
using IM::Login::IMLoginRes;

声明一个自定义类,继承自.grpc.pb.h文件中的service类:

并实现其中的虚函数

class IMLoginServiceImpl : public ImLogin::Service {
    // 注册
    virtual  Status Regist(ServerContext* context, const IMRegistReq* request, IMRegistRes* response) override {
        std::cout << "Regist user_name: " << request->user_name() << std::endl;

        response->set_user_name(request->user_name());
        response->set_user_id(10);
        response->set_result_code(0);

        return Status::OK;
    }
 
    // 登录
    virtual  Status Login(ServerContext* context, const IMLoginReq* request, IMLoginRes* response) override {
        std::cout << "Login user_name: " << request->user_name() << std::endl;
        response->set_user_id(10);
        response->set_result_code(0);
        return Status::OK;
    }
  
};

最后,实现业务逻辑,绑定ip+port,进行服务监听

void RunServer() 
{
    std::string server_addr("0.0.0.0:50051");

    // 创建一个服务类
    IMLoginServiceImpl service;
  
    ServerBuilder builder;

    builder.AddListeningPort(server_addr, grpc::InsecureServerCredentials());
    builder.AddChannelArgument(GRPC_ARG_KEEPALIVE_TIME_MS, 5000);
    builder.AddChannelArgument(GRPC_ARG_KEEPALIVE_TIMEOUT_MS, 10000);
    builder.AddChannelArgument(GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS, 1);
    builder.RegisterService(&service);
   
    //创建/启动
    std::unique_ptr<Server> server(builder.BuildAndStart());
    std::cout << "Server listening on " << server_addr << std::endl;
    // 进入服务循环
    server->Wait();
}

int main(int argc, const char** argv)
{
    RunServer();
    return 0;
}

客户端代码
首先创建client.cc文件,声明头文件,开放命名空间:

#include <iostream>
#include <memory>
#include <string>
// /usr/local/include/grpcpp/grpcpp.h
#include <grpcpp/grpcpp.h>

// 包含我们自己proto文件生成的.h
#include "IM.Login.pb.h"
#include "IM.Login.grpc.pb.h"

// 命名空间
// grcp
using grpc::Channel;
using grpc::ClientContext;
using grpc::Status;
// 自己proto文件的命名空间
using IM::Login::ImLogin;
using IM::Login::IMRegistReq;
using IM::Login::IMRegistRes;
using IM::Login::IMLoginReq;
using IM::Login::IMLoginRes;

实现客户端逻辑:

class ImLoginClient
{
public:
    ImLoginClient(std::shared_ptr<Channel> channel)
        :stub_(ImLogin::NewStub(channel)) {

    }
    void Regist(const std::string &user_name, const std::string &password) {
        IMRegistReq request;
        request.set_user_name(user_name);
        request.set_password(password);
        
        IMRegistRes response;
        ClientContext context;
        std::cout <<  "-> Regist req" << std::endl;
        Status status = stub_->Regist(&context, request, &response);
        if(status.ok()) {
            std::cout <<  "user_name:" << response.user_name() << ", user_id:" << response.user_id() << std::endl;
        } else {
            std::cout <<  "user_name:" << response.user_name() << "Regist failed: " << response.result_code()<< std::endl;
        }
    }

     void Login(const std::string &user_name, const std::string &password) {
        IMLoginReq request;
        request.set_user_name(user_name);
        request.set_password(password);
        
        IMLoginRes response;
        ClientContext context;
        std::cout <<  "-> Login req" << std::endl;
        Status status = stub_->Login(&context, request, &response);
        if(status.ok()) {
            std::cout <<  "user_id:" << response.user_id() << " login ok" << std::endl;
        } else {
            std::cout <<  "user_name:" << request.user_name() << "Login failed: " << response.result_code()<< std::endl;
        }
    }

private:
    std::unique_ptr<ImLogin::Stub> stub_;
};
int main() 
{
    // 服务器的地址
    std::string server_addr = "localhost:50051";
    ImLoginClient im_login_client(
        grpc::CreateChannel(server_addr, grpc::InsecureChannelCredentials())
    );
    std::string user_name = "wjq++";
    std::string password = "123456";
    im_login_client.Regist(user_name, password);
    im_login_client.Login(user_name, password);

    return 0;
}

在Windows10上编译grpc工程,得到protoc.exe和grpc_cpp_plugin.exe

使用protoc.exe编译得到 protobuf文件

转自:在Windows10上编译grpc工程,得到protoc.exe和grpc_cpp_plugin.exe-CSDN博客

 grpc是google于2015年发布的一款跨进程、跨语言、开源的RPC(远程过程调用)技术。使用C/S模式,在客户端、服务端共享一个protobuf二进制数据。在点对点通信、微服务、跨语言通信等领域应用很广,下面介绍grpc在windows10上编译,这里以编译grpc v1.42.0版本为例,进行说明,如图(1)所示:

https://github.com/grpc/grpc/tree/v1.42.0/
1

图(1) 下载grpc v1.42.0版本

1 安装编译工具
1.1 安装VS2019
    下载VS2019,官网地址: https://visualstudio.microsoft.com/zh-hans/vs/older-downloads/
    个人地址: https://pan.baidu.com/s/1VaQC5_CprbTtp8mbPWCaBA
提取码:uo1b
    双击该安装包,选中"使用C++的桌面开发",然后一路默认,直到安装完成。


图(2) 下载VS2019


图(3) 选中“使用C++的桌面开发”即可

1.2 安装git
    git官网: ttps://git-scm.com/
    git的安装方法进,参考这篇文件: git详细安装教程

1.3 安装cmake
    cmake官网: https://cmake.org/download/
    cmake的安装方法,参考这篇文件: cmake安装

1.4 安装nasm
    nasm官网: https://www.nasm.us/
    nasm的安装方法,参考这篇文件: nasm安装

1.5 安装ninja
    ninja官网: https://ninja-build.org/
    ninja的安装方法,参考这篇文件: ninja安装

2 配置工程
2.1 Git配置ssh
    git配置ssh请参考这篇文章: https://www.cnblogs.com/yiven/p/8465054.html

2.2 修改zlib的版本号
    将grpc\third_party\zlib\CMakeLists.txt里的第一行cmake版本号,改成如下:

cmake_minimum_required(VERSION 2.8...3.22)
1
2.3 下载第三方依赖包
    在https://github.com/grpc/grpc/tree/v1.42.0/third_party链接里,

https://github.com/grpc/grpc/tree/v1.42.0/third_party
1
    下载编译所需的第三方依赖包,具体如下:

abseil-cpp
benchmark
bloaty
boringssl
c-ares
data-plane-api
googleapis
googletest
libuv
opencensus-proto
opentelemetry-proto
protobuf
protoc-gen-validate
re2
xds
zlib
    将这些第三方依赖包下载后,解压,把它们放到grpc\third_party的同名目录里。


图(4) 手动下载第三方依赖包

    或者,在这个链接里下载: https://pan.baidu.com/s/1fplVSH39XML3pRnshFGnVA 提取码:dair

3 使用cmake编译grpc
    打开Git ,克隆grpc工程,然后,设置第三方的依赖库,再使用make命令编译。

## 1) 克隆grpc工程
git clone --recurse-submodules -b v1.42.0 https://gitee.com/mirrors/grpc

## 2) 进入grpc工程
cd grpc

## 3) 同步第三方模块
git submodule sync

## 4)使用VS2019构建静态库
cmake -G "Visual Studio 16 2019" -DgRPC_INSTALL=ON -DgRPC_BUILD_TESTS=OFF ./CMakeLists.txt

## 5) 设置Debug目录,并编译
cmake --build . --config Debug

## 6) 设置Release目录,并编译
cmake --build . --config Release

4 生成protobuf文件
4.1 提取protoc
    编译成功后,在grpc\third_party\protobuf\Release目录,会看到protoc.exe、libprotoc.lib等文件;
    在grpc\Release\grpc_cpp_plugin.exe、grpc_csharp_plugin.exe,将其拷贝出来,放到D:\protobuf,如图(5)所示:


图(5) 拷贝protoc.exe、grpc_cpp_plugin.exe、grpc_csharp_plugin.exe

4.2 创建一个helloworld.proto文件
    helloworld.proto的内容如下:
    //helloworld.proto

syntax = "proto3";

option java_multiple_files = true;
option java_package = "io.grpc.examples.helloworld";
option java_outer_classname = "HelloWorldProto";
option objc_class_prefix = "HLW";

package helloworld;

// The greeting service definition.
service Greeter {
  // Sends a greeting
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}

// The request message containing the user's name.
message HelloRequest {
  string name = 1;
}

// The response message containing the greetings
message HelloReply {
  string message = 1;
}

4.3 生成pb文件
    按Win+R快捷键,输入:cmd,依次输入如下命令:

## 1)切换到D盘
D:

## 2)进入protobuf目录
D:\protobuf

## 3)执行C++方式的protoc命令
 //  protoc.exe -I=.\ --cpp_out=.\ --grpc_out=.\ --plugin=protoc-gen-grpc=".\grpc_cpp_plugin.exe" //  helloworld.proto

D:\Test\grpc\builds\third_party\protobuf\Debug\protoc.exe   --cpp_out=. --grpc_out=. --plugin=protoc-gen-grpc="grpc_cpp_plugin.exe" helloworld.proto

## 4) 执行Csharp方式的protoc命令
protoc.exe -I=.\ --csharp_out=.\ --grpc_out=.\ --plugin=protoc-gen-grpc=".\grpc_csharp_plugin.exe" helloworld.proto

    本例采用C++方式的protoc命令,如图(6)所示:

protoc.exe -I=.\ --cpp_out=.\ --grpc_out=.\ --plugin=protoc-gen-grpc=".\grpc_cpp_plugin.exe" helloworld.proto
1

图(6) 按C++方式,生成pb文件

    或按C# (CSharp)方式,生成pb文件,如图(7)所示:


图(7)按C#(CSharp)方式,生成pb文件

5 C++和C#版本的protoc
5.1 C++、C#共同的protoc
    protoc是根据插件grpc_XXX_plugin.exe和命令 --XXX_out 参数,来生成不同语言的pb文件的。protoc.exe既可以共用,也可以单独分开。这里介绍共用的protoc,如图(8)所示表示不同的插件:


图(8) grpc_XXX_plugin.exe表示不同的语言插件

    grpc通过protoc文件,进行数据传递。这里给出C++和C#版本protoc链接: https://pan.baidu.com/s/1RjUeI-89M8FkYuXDCMsMFg 提取码:s56c

    对于其他语言版本的protoc,比如Java、Note.js、Ruby、Python等版本的protoc,需要按照本文第1~4节来编译grpc源码,在grpc\Release和grpc\thitd_party\protobuf\Release目录,就可以得到protoc。

5.2 C#单独的protoc
    C#版本的protoc,在NuGet.org里有官方版本下载,它放在Grpc.Tools工具里,如图(9)所示:

https://www.nuget.org/packages/Grpc.Tools/2.57.0#show-readme-container
1

图(9) 下载Grpc.Tools工具,该包是C#版本的protoc包

    下载Grpc.Tools工具,得到以*.nupkg结尾的压缩包,这个*.nupkg后缀名改成*.rar,如图(10)所示:


图(10) 下载Grpc.Tools,并修改后缀名

    然后将这rar文件解压,在grpc.tools\tools\windows_x64目录下,即可看到protoc.exe、gprc_csharp_plugin.exe文件,这2个文件用于生成C#版本grpc对应的pb文件,如图(11)所示:


图(11) 在grpc.tools\tools\windows_x64里

以下是在 Windows 上编译 gRPC 的详细步骤: 1. 安装 Git 和 Visual Studio 在 Windows 上编译 gRPC,您需要先安装 Git 和 Visual Studio。您可以从以下链接下载和安装它们: - Git:https://git-scm.com/downloads - Visual Studio:https://visualstudio.microsoft.com/downloads/ 2. 克隆 gRPC 代码库 打开 Git Bash 或者其他命令行工具,输入以下命令来克隆 gRPC 代码库: ``` git clone -b v1.38.x https://github.com/grpc/grpc.git ``` 3. 安装依赖库 在 Windows 上编译 gRPC,您还需要安装一些依赖库,包括 OpenSSL 和 protobuf。您可以使用 vcpkg 工具来安装它们。以下是安装步骤: - 下载 vcpkg 工具:https://github.com/microsoft/vcpkg - 打开命令行工具,进入 vcpkg 目录,使用以下命令安装 OpenSSL 和 protobuf: ``` .\vcpkg.exe install openssl:x64-windows protobuf:x64-windows ``` 4. 生成 Visual Studio 解决方案和项目 进入 gRPC 代码库的根目录,在命令行工具中输入以下命令来生成 Visual Studio 解决方案和项目: ``` mkdir cmake_build cd cmake_build cmake -G "Visual Studio 16 2019" -A x64 -DCMAKE_TOOLCHAIN_FILE=..\third_party\vcpkg\scripts\buildsystems\vcpkg.cmake -DgRPC_SSL_PROVIDER=package -DgRPC_ZLIB_PROVIDER=package .. ``` 5. 构建 gRPC 打开生成的 Visual Studio 解决方案,选择 "Release" 配置,然后构建 gRPC 项目。 您可以使用 Visual Studio 中的菜单或者使用以下命令来构建: ``` cmake --build . --config Release ``` 6. 运行测试 构建完成后,在命令行工具中输入以下命令来运行 gRPC 的测试: ``` cd grpc cmake --build . --config Release --target grpc_cli cd cmake_build ctest -C Release --output-on-failure -j 4 ``` 以上就是在 Windows 上编译 gRPC 的步骤。注意,实际情况可能会因不同的环境而有所不同,这只是一个简单的指南。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值