這篇文章將會簡單的描述一下grpc+protobuf 的C++ service的搭建過程,告訴讀者在linux系統下怎樣實現一個service接口的流程。linux
1、.proto文件的ios
實現一個簡單的helloworld回顯功能,首先須要一個.proto文件,我將它命名爲example.proto,文件內容以下:c++
[cpp] view plain copy服務器
syntax = "proto3"; message SearchRequest { string Request = 1; } message SearchResponse { string Response = 2; } service SearchService { rpc Search (SearchRequest) returns (SearchResponse); }
2、自動生成代碼ide
使用example.proto文件自動生成grpc和protobuf的代碼ui
[cpp] view plain copyc++11
protoc --cpp_out=./ examples.proto protoc --grpc_out=./ --plugin=protoc-gen-grpc=/usr/local/bin/grpc_cpp_plugin examples.proto
這兩個命令將會生成四個文件,examples.grpc.pb.cc、examples.grpc.pb.h、examples.pb.cc、examples.pb.h。code
3、服務器代碼server
[cpp] view plain copy接口
#include <iostream> #include <memory> #include <string> #include <grpc++/grpc++.h> #include <grpc/grpc.h> #include <grpc++/server.h> #include <grpc++/server_builder.h> #include <grpc++/server_context.h> #include "examples.grpc.pb.h" using grpc::Server; using grpc::ServerBuilder; using grpc::ServerContext; using grpc::Status; class SearchRequestImpl final : public SearchService::Service { Status Search(ServerContext* context, const SearchRequest* request, SearchResponse* reply) override { std::string prefix("Hello "); reply->set_response(prefix + request->request()); return Status::OK; } }; void RunServer() { std::string server_address("0.0.0.0:50051"); SearchRequestImpl service; ServerBuilder builder; builder.AddListeningPort(server_address, grpc::InsecureServerCredentials()); builder.RegisterService(&service); std::unique_ptr<Server> server(builder.BuildAndStart()); std::cout << "Server listening on " << server_address << std::endl; server->Wait(); } int main(int argc, char** argv) { RunServer(); return 0; }
4、客戶端代碼
[cpp] view plain copy
#include <iostream> #include <memory> #include <string> #include <grpc++/grpc++.h> #include <grpc/support/log.h> #include "examples.grpc.pb.h" using grpc::Channel; using grpc::ClientAsyncResponseReader; using grpc::ClientContext; using grpc::CompletionQueue; using grpc::Status; class ExampleClient { public: explicit ExampleClient(std::shared_ptr<Channel> channel) : stub_(SearchService::NewStub(channel)) {} std::string Search(const std::string& user) { SearchRequest request; request.set_request(user); SearchResponse reply; ClientContext context; CompletionQueue cq; Status status; std::unique_ptr<ClientAsyncResponseReader<SearchResponse> > rpc( stub_->AsyncSearch(&context, request, &cq)); rpc->Finish(&reply, &status, (void*)1); void* got_tag; bool ok = false; GPR_ASSERT(cq.Next(&got_tag, &ok)); GPR_ASSERT(got_tag == (void*)1); GPR_ASSERT(ok); if (status.ok()) { return reply.response(); } else { return "RPC failed"; } } private: std::unique_ptr<SearchService::Stub> stub_; }; int main(int argc, char** argv) { ExampleClient client(grpc::CreateChannel( "localhost:50051", grpc::InsecureChannelCredentials())); std::string user("world"); std::string reply = client.Search(user); // The actual RPC call! std::cout << "client received: " << reply << std::endl; return 0; }
5、Makefile文件
[cpp] view plain copy
subdir = ./ export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig SOURCES = $(wildcard $(subdir)*.cc) SRCOBJS = $(patsubst %.cc,%.o,$(SOURCES)) CC = g++ %.o:%.cc $(CC) -std=c++11 -I/usr/local/include -pthread -c $< -o $@ all: client server client: examples.grpc.pb.o examples.pb.o examples_client.o $(CC) $^ -L/usr/local/lib `pkg-config --libs grpc++ grpc` -Wl,--no-as-needed -lgrpc++_reflection -Wl,--as-needed -lprotobuf -lpthread -ldl -lssl -o $@ server: examples.grpc.pb.o examples.pb.o examples_server.o $(CC) $^ -L/usr/local/lib `pkg-config --libs grpc++ grpc` -Wl,--no-as-needed -lgrpc++_reflection -Wl,--as-needed -lprotobuf -lpthread -ldl -lssl -o $@ #chmod 777 $@ clean: sudo rm *.o
6、運行
運行./server啓動service,在另外一個端口運行./client 打印出:client received: Hello world表示兩邊已通,grpc+protobuf 搭建完成。