当前位置: 首页 > news >正文

Ubuntu快速安装使用gRPC C++

目录

  • 引言
  • 一、快速安装
    • 1. 安装必要依赖库
      • 1.1 安装 cmake
      • 1.2 安装 gcc g++
    • 2. 安装gRPC
  • 二、测试使用
  • 三、参考博客

引言

关于gRPC随着云原生微服务的火热也流行了起来,而且学好一个gRPC框架对目前来说也是必须的了。然而对于一个基础的小白来说,这个gRPC的框架运用起来是及其的困难,具体体现在依赖库繁多,且大部分需要对git进行代理,在实际运用框架时,常常会发现某些库或者头文件找不到了,常常是些编译链接错误,还是很烦的。本篇文章通过博主自己整理的非常简单的操作来让新手小白进行一个友好的入门,并且对于博主自己也是一个笔记的作用,并且对于一些用到的第三方库也给出了百度网盘的链接,跟着步骤来还是很容易上手的,也没什么废话,跟着教程实操起来吧!

一、快速安装

安装所需要的第三方库-百度网盘链接

1. 安装必要依赖库

执行以下命令安装

sudo apt update
sudo apt install -y protobuf-compiler libprotobuf-dev  # 安装protobuf编译器和库
sudo apt install -y build-essential autoconf libtool pkg-config libsystemd-dev libssl-dev  # 安装依赖项
sudo apt install -y libgflags-dev libgtest-dev libc++-dev clang  # 安装c++支持
sudo apt-get install autoconf automake libtool  # 依赖工具

如果cmake低于3.15, gcc/g++ 低于 7.0,则按照如下方法安装,否则跳到 2.安装gRPC

cmake --version
gcc -v
g++ -v

1.1 安装 cmake

安装CMake需要的第三方库-百度网盘链接

sudo apt-get autoremove cmake  # 卸载已经安装的旧版的CMake
tar zxvf cmake-3.23.0-linux-x86_64.tar.gz  # 解压cmake安装包
sudo mv cmake-3.23.0-linux-x86_64 /opt/cmake-3.23.0
sudo ln -sf /opt/cmake-3.23.0/bin/*  /usr/bin/
cmake -version  # 显示cmake version 3.23.0 说明已经成功

1.2 安装 gcc g++

sudo apt-get install -y software-properties-common  # 安装
sudo add-apt-repository ppa:ubuntu-toolchain-r/test
sudo apt update
sudo apt install g++-7 -y
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-7 60 \  
                         --slave /usr/bin/g++ g++ /usr/bin/g++-7  # 建立软连接并检查
sudo update-alternatives --config gcc
gcc -v
g++ -v  # 显示7.5的版本

2. 安装gRPC

安装gRPC需要的第三方库-百度网盘链接

tar -jxf grpc-v1.45.2.tar.bz2
cd grpc-v1.45.2 
mkdir -p cmake/build
cd cmake/build
cmake ../..
make -j 4
sudo make install  # 安装到系统目录

二、测试使用

先运行以下命令创建测试文件,然后将文件中的内容填充到对应的文件里

mkdir gRPC-test
cd gRPC-test
touch client.cc  CMakeLists.txt  helloworld.proto  server.cc

helloworld.proto

syntax = "proto3";

package helloworld;

service Greeter {
  rpc SayHello (HelloRequest) returns (HelloResponse) {}
}

message HelloRequest {
  string name = 1;
}

message HelloResponse {
  string message = 1;
}

CMakeLists.txt

cmake_minimum_required(VERSION 3.10)

project(helloworld)

set(CMAKE_CXX_STANDARD 17)

set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR})

# 查找 Protobuf 库
find_package(Protobuf CONFIG REQUIRED)
find_package(gRPC CONFIG REQUIRED)

# 添加 server 可执行程序
add_executable(server 
  server.cc helloworld.grpc.pb.cc helloworld.pb.cc
)
# 添加对 protobuf 和 gRPC 库的链接
target_link_libraries(server PRIVATE 
  gRPC::grpc++  # CMake 提供的目标库名称
  gRPC::grpc++_reflection  # CMake 提供的目标库名称
  protobuf::libprotobuf  # CMake 提供的目标库名称
)

# 添加 client 可执行程序
add_executable(client 
  client.cc helloworld.grpc.pb.cc helloworld.pb.cc
)
# 添加对 protobuf 和 gRPC 库的链接
target_link_libraries(client PRIVATE
  gRPC::grpc++
  gRPC::grpc++_reflection
  protobuf::libprotobuf
)

server.cc

#include <iostream>
#include <memory>
#include <string>

#include <grpcpp/grpcpp.h>
#include "helloworld.grpc.pb.h"

using grpc::Server;
using grpc::ServerBuilder;
using grpc::ServerContext;
using grpc::Status;
using helloworld::Greeter;
using helloworld::HelloRequest;
using helloworld::HelloResponse;

// Logic and data behind the server's behavior.
class GreeterServiceImpl final : public Greeter::Service {
  Status SayHello(ServerContext* context, const HelloRequest* request,
                  HelloResponse* reply) override {
    std::string prefix("Hello ");
    reply->set_message(prefix + request->name());
    return Status::OK;
  }
};

void RunServer() {
  std::string server_address("0.0.0.0:50051");
  GreeterServiceImpl service;

  ServerBuilder builder;
  // Listen on the given address without any authentication mechanism.
  builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());
  // Register "service" as the instance through which we'll communicate with
  // clients. In this case it corresponds to an *synchronous* service.
  builder.RegisterService(&service);
  // Finally assemble the server.
  std::unique_ptr<Server> server(builder.BuildAndStart());
  std::cout << "Server listening on " << server_address << std::endl;

  // Wait for the server to shutdown. Note that some other thread must be
  // responsible for shutting down the server for this call to ever return.
  server->Wait();
}

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

client.cc

#include <iostream>
#include <memory>
#include <string>

#include <grpcpp/grpcpp.h>
#include "helloworld.grpc.pb.h"

using grpc::Channel;
using grpc::ClientContext;
using grpc::Status;
using helloworld::Greeter;
using helloworld::HelloRequest;
using helloworld::HelloResponse;

class GreeterClient {
 public:
  GreeterClient(std::shared_ptr<Channel> channel)
      : stub_(Greeter::NewStub(channel)) {}

  // Assembles the client's payload, sends it and presents the response back
  // from the server.
  std::string SayHello(const std::string& user) {
    // Data we are sending to the server.
    HelloRequest request;
    request.set_name(user);

    // Container for the data we expect from the server.
    HelloResponse reply;

    // Context for the client. It could be used to convey extra information to
    // the server and/or tweak certain RPC behaviors.
    ClientContext context;

    // The actual RPC.
    Status status = stub_->SayHello(&context, request, &reply);

    // Act upon its status.
    if (status.ok()) {
      return reply.message();
    } else {
      std::cout << status.error_code() << ": " << status.error_message()
                << std::endl;
      return "RPC failed";
    }
  }

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

int main(int argc, char** argv) {
  // Instantiate the client. It requires a channel, out of which the actual RPCs
  // are created. This channel models a connection to an endpoint specified by
  // the argument "--target=" which is the only expected argument.
  // We indicate that the channel isn't authenticated (use of
  // InsecureChannelCredentials()).
  std::string target_str;
  std::string arg_str("--target");
  if (argc > 1) {
    std::string arg_val = argv[1];
    size_t start_pos = arg_val.find(arg_str);
    if (start_pos != std::string::npos) {
      start_pos += arg_str.size();
      if (arg_val[start_pos] == '=') {
        target_str = arg_val.substr(start_pos + 1);
      } else {
        std::cout << "The only correct argument syntax is --target=" << std::endl;
        return 0;
      }
    } else {
      std::cout << "The only acceptable argument is --target=" << std::endl;
      return 0;
    }
  } else {
    target_str = "localhost:50051";
  }
  GreeterClient greeter(grpc::CreateChannel(
      target_str, grpc::InsecureChannelCredentials()));
  std::string user("world");
  std::string reply = greeter.SayHello(user);
  std::cout << "Greeter received: " << reply << std::endl;

  return 0;
}

执行以下命令进行编译生成可执行程序

protoc -I=. --grpc_out=./ --cpp_out=./ --plugin=protoc-gen-grpc=`which grpc_cpp_plugin` ./helloworld.proto  # 生成.pb.h .pb.cc .grpc.pb.h .grpc.pb.cc
mkdir build
cd build
cmake ..  # 生成Makefile文件
make  # 编译

然后打开两个终端运行程序,出现如下图说明已经测试成功啦

./server  # 第一个shell
./client  # 第二个shell

在这里插入图片描述

三、参考博客

参考博客-知乎
参考博客-CSDN

相关文章:

  • Oracle 数据库 HugePages 配置详解:提升性能的关键步骤
  • C语言学习笔记(第三部份)
  • 解决: 由于embedding 模型不可用,需要配置默认embedding 模型
  • 【Go每日一练】随机密码生成器
  • 从数据清洗到模型调优的全流程实战
  • 【AutoFormer 源码理解】
  • 从“自习室令牌”到线程同步:探秘锁与条件变量
  • 基于Python的tkinter开发的一个工具,解析图片文件名并将数据自动化导出为Excel文件
  • 深度学习pytorch笔记:TCN
  • 从零开始使用 **Taki + Node.js** 实现动态网页转静态网站的完整代码方案
  • 谈谈 TypeScript 中的联合类型(union types)和交叉类型(intersection types),它们的应用场景是什么?
  • 代码随想录算法训练营第34天 | 62.不同路径 63. 不同路径 II 整数拆分 不同的二叉搜索树 (跳过)
  • linux(centos8)下编译ffmpeg
  • HCIA-PPP
  • 每天五分钟深度学习PyTorch:循环神经网络RNN的计算以及维度信息
  • 大数据 Spark 技术简介
  • TLSR8355F128芯片特色解析
  • Linux中的epoll简单使用案例
  • 视频转音频, 音频转文字
  • 通过socket实现文件上传和下载功能
  • 习近平出席中拉论坛第四届部长级会议开幕式并发表主旨讲话
  • 俄乌拟在土耳其举行会谈,特朗普:我可能飞过去
  • 山西省委常委李金科添新职
  • 国务院新闻办公室发布《新时代的中国国家安全》白皮书
  • 默茨首访聚焦欧洲,欲推欧洲防务自主
  • 家电维修担心遇“李鬼”?上海推动“物业+专业服务”进社区