grpc 的安装
C++使用grpc首先需在电脑上安装grpc和protobuf,grpc的安装只推荐使用下面方式
安装依赖
- 配置工具:build-essential, autoconf, libtool
- 测试支持:libgflags-dev
- 编译工具:clang, libc+±dev
从官方仓库克隆并编译安装
-
git clone https://github.com/grpc/grpc.git 或者 git clone -b $(curl -L https://grpc.io/release) https://github.com/grpc/grpc
-
cd grpc
-
git submodule update --init
#会自动下载grpc编译依赖的第三方库 -
sudo make && make install
protobuf的安装
git clone https://github.com/google/protobuf
./autogen.sh # 生成 configure 文件
./configure
make
make check
sudo make install
sudo ldconfig
c++grpc 回射服务器的实现
- 首先定义proto文件,echo_sample.proto
syntax = "proto3";
package echosample;
service Reflecter {
rpc Refect(EchoRequest) returns (EchoReply) {}
}
message EchoRequest {
string request_msg = 1;
}
message EchoReply {
string reply_msg = 1;
}
- server的试下你代码echo_sample_server.cc
#include <iostream>
#include <memory>
#include <string>
#include <grpcpp/grpcpp.h>
#ifdef BAZEL_BUILD
#include "examples/protos/echo_sample.grpc.pb.h"
#else
#include "echo_sample.grpc.pb.h"
#endif
using grpc::Server;
using grpc::ServerBuilder;
using grpc::ServerContext;
using grpc::Status;
using echosample::EchoRequest;
using echosample::EchoReply;
using echosample::Reflecter;
// Logic and data behind the server's behavior.
class GreeterServiceImpl final : public Reflecter::Service {
Status Refect(ServerContext* context, const EchoRequest* request,
EchoReply* reply) override {
reply->set_reply_msg(request->request_msg());
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的代码实现echo_sample_client.cc
#include <iostream>
#include <memory>
#include <string>
#include <grpcpp/grpcpp.h>
#ifdef BAZEL_BUILD
#include "examples/protos/echo_sample.grpc.pb.h"
#else
#include "echo_sample.grpc.pb.h"
#endif
using grpc::Channel;
using grpc::ClientContext;
using grpc::Status;
using echosample::EchoRequest;
using echosample::EchoReply;
using echosample::Reflecter;
class GreeterClient {
public:
GreeterClient(std::shared_ptr<Channel> channel)
: stub_(Reflecter::NewStub(channel)) {}
// Assembles the client's payload, sends it and presents the response back
// from the server.
std::string Refect(const std::string& msg) {
// Data we are sending to the server.
EchoRequest request;
request.set_request_msg(msg);
// Container for the data we expect from the server.
EchoReply 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_->Refect(&context, request, &reply);
// Act upon its status.
if (status.ok()) {
return reply.reply_msg();
} else {
std::cout << status.error_code() << ": " << status.error_message()
<< std::endl;
return "RPC failed";
}
}
private:
std::unique_ptr<Reflecter::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()).
GreeterClient greeter(grpc::CreateChannel(
"localhost:50051", grpc::InsecureChannelCredentials()));
char sendline[4096] = {0};
while(fgets(sendline, 4096, stdin) != NULL) {
std::string reply = greeter.Refect(sendline);
std::cout << "Greeter received: " << reply << std::endl;
memset(sendline,0x00,4096);
}
return 0;
}
- Makefile文件,这个Makefile文件我只是把examples中改了一下,proto文件的路径不对,需要在Makefile中自行修改PROTOS_PATH的值,是你编译的相对路径
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++`\
-pthread\
-lgrpc++_reflection\
-ldl
else
LDFLAGS += -L/usr/local/lib `pkg-config --libs protobuf grpc++`\
-pthread\
-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 echo_sample_client echo_sample_server
echo_sample_client: echo_sample.pb.o echo_sample.grpc.pb.o echo_sample_client.o
$(CXX) $^ $(LDFLAGS) -o $@
echo_sample_server: echo_sample.pb.o echo_sample.grpc.pb.o echo_sample_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 echo_sample_client echo_sample_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