grpc使用教程

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 --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;
}

推荐学习 https://xxetb.xetslk.com/s/p5Ibb

  • 27
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
以下是在 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
发出的红包

打赏作者

wjq++

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值