gRPC的使用(cpp)

gRPC是google开源的一套实现rpc调用的框架,支持多种语言,并且比较易用,其数据传输是通过google自家的protobuf来序列化的,下面我们通过改写gRPC的example来实现获取远程host内存的功能。

例子中的文件目录结构如下

./examples/cpp/sysproc
./examples/cpp/sysproc/sysproc_server.cc
./examples/cpp/sysproc/Makefile
./examples/protos/sysproc.proto

1.先定义protobuf文件

文件描述了接口的参数结构和接口结构
sysproc.proto

syntax = "proto3";

service SysProcManager {
    rpc getSysProc (NullMessage) returns (SysProc) {}
}

message NullMessage {}

message SysProc {
    int32 memfree = 1;
};

由于这里的接口必须需要参数,所以我们增加了一个Null类型的消息
我们定义了一个SysProc消息结构用于getSysProc rpc方法的返回值,service的名字叫SysProcManager

服务器端代码

sysproc_service.cc

#include "sysproc.grpc.pb.h"
#include <iostream>
#include <memory>
#include <string>
#include <grpc++/grpc++.h>
extern "C" {
#include <sys/sysinfo.h>
}


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

// Logic and data behind the server's behavior.
class SysProcServiceImpl final : public SysProcManager::Service {
  Status getSysProc(ServerContext* context, const NullMessage* request,
                SysProc * reply) override {
    int memFree = 0;
    struct sysinfo info;
    sysinfo(&info);
    memFree = (int)(info.freeram);
    reply->set_memfree(memFree);
    return Status::OK;
  }
};

void RunServer() {
  std::string server_address("0.0.0.0:50051");
  SysProcServiceImpl 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;
}

SysProcServiceImpl先定义了一个Service类继承自我们刚刚定义的protobuf文件编译产生的grpc的文件SysProcManager::Service,并实现getSysProc,在后面的Makefile文件中会看到编译的过程
通过ServiceBuilder创建一个builder并监听服务器端口,然后注册我们刚刚写的Service类,这时候就wait处理客户端请求就好了

sysproc_client.cc

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

#include <grpc++/grpc++.h>

#include "sysproc.grpc.pb.h"

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

class SysProcClient {
 public:
 //创建客户端类,该类通过一个SysProcManager(protobuf定义的Service)的stub来和服务器端进行通信
  SysProcClient(std::shared_ptr<Channel> channel)
      : stub_(SysProcManager::NewStub(channel)) {}

  // Assembles the client's payload, sends it and presents the response back
  // from the server.
  int getSysProc() {
    // Data we are sending to the server.
    NullMessage request;

    // Container for the data we expect from the server.
    SysProc 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.
    //stub调用生成的接口调用service
    Status status = stub_->getSysProc(&context, request, &reply);

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

 private:
  std::unique_ptr<SysProcManager::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 (in this case,
  // localhost at port 50051). We indicate that the channel isn't authenticated
  // (use of InsecureChannelCredentials()).
  //创建一个chanel用于定义一个和服务器端的网络连接,传给client的stub
  SysProcClient sysproc_client(grpc::CreateChannel(
      "localhost:50051", grpc::InsecureChannelCredentials()));
  int reply = sysproc_client.getSysProc();
  std::cout << "Client received: " << reply << std::endl;

  return 0;
}

Makefile:

HOST_SYSTEM = $(shell uname | cut -f 1 -d_)
SYSTEM ?= $(HOST_SYSTEM)
CXX = g++
CPPFLAGS += `pkg-config --cflags protobuf grpc`
CXXFLAGS += -std=c++11
ifeq ($(SYSTEM),Darwin)
LDFLAGS += -L/usr/local/lib `pkg-config --libs protobuf grpc++ grpc`\
           -lgrpc++_reflection\
           -ldl
else
LDFLAGS += -L/usr/local/lib `pkg-config --libs protobuf grpc++ grpc`\
           -Wl,--no-as-needed -lgrpc++_reflection -Wl,--as-needed\
           -ldl
endif
PROTOC = protoc
GRPC_CPP_PLUGIN = grpc_cpp_plugin
GRPC_CPP_PLUGIN_PATH ?= `which $(GRPC_CPP_PLUGIN)`

PROTOS_PATH = ../../protos

vpath %.proto $(PROTOS_PATH)

all: system-check sysproc_client sysproc_server

sysproc_client: sysproc.pb.o sysproc.grpc.pb.o sysproc_client.o
    $(CXX) $^ $(LDFLAGS) -o $@

sysproc_server: sysproc.pb.o sysproc.grpc.pb.o sysproc_server.o
    $(CXX) $^ $(LDFLAGS) -o $@

.PRECIOUS: %.grpc.pb.cc
%.grpc.pb.cc: %.proto
    $(PROTOC) -I $(PROTOS_PATH) --grpc_out=. --plugin=protoc-gen-grpc=$(GRPC_CPP_PLUGIN_PATH) $<

.PRECIOUS: %.pb.cc
%.pb.cc: %.proto
    $(PROTOC) -I $(PROTOS_PATH) --cpp_out=. $<

clean:
    rm -f *.o *.pb.cc *.pb.h sysproc_client sysproc_server


# The following is to test your system and ensure a smoother experience.
# They are by no means necessary to actually compile a grpc-enabled software.

PROTOC_CMD = which $(PROTOC)
PROTOC_CHECK_CMD = $(PROTOC) --version | grep -q libprotoc.3
PLUGIN_CHECK_CMD = which $(GRPC_CPP_PLUGIN)
HAS_PROTOC = $(shell $(PROTOC_CMD) > /dev/null && echo true || echo false)
ifeq ($(HAS_PROTOC),true)
HAS_VALID_PROTOC = $(shell $(PROTOC_CHECK_CMD) 2> /dev/null && echo true || echo false)
endif
HAS_PLUGIN = $(shell $(PLUGIN_CHECK_CMD) > /dev/null && echo true || echo false)

SYSTEM_OK = false
ifeq ($(HAS_VALID_PROTOC),true)
ifeq ($(HAS_PLUGIN),true)
SYSTEM_OK = true
endif
endif

system-check:
ifneq ($(HAS_VALID_PROTOC),true)
    @echo " DEPENDENCY ERROR"
    @echo
    @echo "You don't have protoc 3.0.0 installed in your path."
    @echo "Please install Google protocol buffers 3.0.0 and its compiler."
    @echo "You can find it here:"
    @echo
    @echo "   https://github.com/google/protobuf/releases/tag/v3.0.0"
    @echo
    @echo "Here is what I get when trying to evaluate your version of protoc:"
    @echo
    -$(PROTOC) --version
    @echo
    @echo
endif
ifneq ($(HAS_PLUGIN),true)
    @echo " DEPENDENCY ERROR"
    @echo
    @echo "You don't have the grpc c++ protobuf plugin installed in your path."
    @echo "Please install grpc. You can find it here:"
    @echo
    @echo "   https://github.com/grpc/grpc"
    @echo
    @echo "Here is what I get when trying to detect if you have the plugin:"
    @echo
    -which $(GRPC_CPP_PLUGIN)
    @echo
    @echo
endif
ifneq ($(SYSTEM_OK),true)
    @false
endif

运行

先运行服务器sysproc_server,再运行sysproc_client就能看到结果的

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值