4.4.3 grpc for c++使用案例
1、 proto文件编辑
player.proto
syntax = "proto3";
package Player;
// 定义服务
service Greeter {
// 定义服务函数
rpc SayHello (HelloRequest) returns (HelloReply) {}
rpc PlayStart (PlayStartReq) returns (PlayStartRes){}
}
// 定义SayHello服务的请求结构
message HelloRequest {
string name = 1;
string test = 2;
}
// 定义SayHello服务的响应结构
message HelloReply {
string message = 1;
}
// 定义播放请求结构
message PlayStartReq {
uint32 sessionid = 1;
string eleStmName = 2;
}
// 定义播放响应结构
message PlayStartRes{
int32 result = 1;
string extension = 2;
}
第二行:包的名字 package Player; 是 Player
第五行:grpc服务的名称 service Greeter 是 Greeter
后面的请求响应结构,无论名字是大写还是小写,最终调用的时候都是小写。
2、生成C++代码
protoc --cpp_out=. player.proto
protoc --cpp_out=. --grpc_out=. --plugin=protoc-gen-grpc=/usr/local/bin/grpc_cpp_plugin player.proto
生成C++代码player.pb.h和player.pb.cc。
pkg-config --libs protobuf -L/usr/local/lib/x86_64-linux-gnu -lprotobuf -pthread
3、序列化接口
bool SerializeToString(string* output) const
序列化消息,将消息对象以string方式输出。
bool ParseFromString(const string& data)
反序列化消息,解析给定的string为消息对象
bool SerializeToOstream(ostream* output) const
序列化消息,将消息对象写入给定的c++ ostream中
bool ParseFromIstream(istream* input)
反序列化消息,从给定的c++ istream中解析出消息对象
4、grpc server端
命名空间
记住首先一定要开放命名空间
using grpc::Server;
using grpc::ServerBuilder;
using grpc::ServerContext;
using grpc::Status;
using Player::Greeter;
using Player::HelloReply;
using Player::HelloRequest;
using Player::PlayStartReq;
using Player::PlayStartRes;
重写服务
定义服务端的类,继承 proto 文件定义的 grpc 服务 Greeter ,重写 grpc 服务定义的方法
class GreeterServiceImpl : public Greeter::Service {
//重写 hello 方法
virtual Status SayHello(ServerContext* context, const HelloRequest* request,HelloReply* reply) override {
std::string prefix("Hello ");
std::cout << "test:"<<request->test() << std::endl;
reply->set_message(prefix + request->name());
return Status::OK;
}
//重写 开流 方法
virtual Status PlayStart(ServerContext* context, const PlayStartReq* request,PlayStartRes* reply) override {
std::string prefix("Hello ");
std::cout << "session id:" << request->sessionid() << std::endl;
std::cout << "eleStmName:" << request->elestmname() << std::endl;
reply->set_result(10);
reply->set_extension("extension");
return Status::OK;
}
};
在重写方法的时候可以通过 request 结构里面的成员名函数获取改成员,例如:
message PlayStartReq {
uint32 sessionid = 1;
string eleStmName = 2;
}
const PlayStartReq* request;
std::cout << "session id:" << request->sessionid() << std::endl;
std::cout << "eleStmName:" << request->elestmname() << std::endl;
同时通过 reply 结构里面的 set_ + 成员名 函数设置成员,例如:
message PlayStartRes{
int32 result = 1;
string extension = 2;
}
PlayStartRes* reply;
reply->set_result(10);
reply->set_extension("extension");
启动服务
std::string server_address("0.0.0.0:50051");
/* 定义重写的服务类 */
GreeterServiceImpl service;
/* 创建工厂类 */
ServerBuilder builder;
/* 监听端口和地址 */
builder.AddListeningPort(server_address, 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);
/** 创建和启动一个RPC服务器*/
std::unique_ptr<Server> server(builder.BuildAndStart());
std::cout << "Server listening on " << server_address << std::endl;
/* 进入服务事件循环 */
server->Wait();
完整代码
#include <iostream>
#include <memory>
#include <string>
#include <grpcpp/ext/proto_server_reflection_plugin.h>
#include <grpcpp/grpcpp.h>
#include <grpcpp/health_check_service_interface.h>
#include "player.grpc.pb.h"
#include "player.grpc.pb.h"
using grpc::Server;
using grpc::ServerBuilder;
using grpc::ServerContext;
using grpc::Status;
using Player::Greeter;
using Player::HelloReply;
using Player::HelloRequest;
using Player::PlayStartReq;
using Player::PlayStartRes;
class GreeterServiceImpl : public Greeter::Service {
//重写 hello 方法
virtual Status SayHello(ServerContext* context, const HelloRequest* request,HelloReply* reply) override {
std::string prefix("Hello ");
std::cout << "test:"<<request->test() << std::endl;
reply->set_message(prefix + request->name());
return Status::OK;
}
//重写 开流 方法
virtual Status PlayStart(ServerContext* context, const PlayStartReq* request,PlayStartRes* reply) override {
std::string prefix("Hello ");
std::cout << "session id:" << request->sessionid() << std::endl;
std::cout << "eleStmName:" << request->elestmname() << std::endl;
reply->set_result(10);
reply->set_extension("extension");
return Status::OK;
}
};
void RunServer() {
std::string server_address("0.0.0.0:50051");
/* 定义重写的服务类 */
GreeterServiceImpl service;
/* 创建工厂类 */
ServerBuilder builder;
/* 监听端口和地址 */
builder.AddListeningPort(server_address, 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);
/** 创建和启动一个RPC服务器*/
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;
}
5、 grpc client端
命名空间
记住首先一定要开放命名空间
using grpc::Channel;
using grpc::ClientContext;
using grpc::Status;
using Player::Greeter;
using Player::HelloReply;
using Player::HelloRequest;
using Player::PlayStartReq;
using Player::PlayStartRes;
定义客户端
定义客户端的类,实现两个方法用来发送grpc请求以及接收grpc响应
class GreeterClient
{
public:
GreeterClient(std::shared_ptr<Channel> channel)
: stub_(Greeter::NewStub(channel)) {}
std::string SayHello(const std::string &user)
{
HelloRequest request;
request.set_name(user);
request.set_test("test");
HelloReply reply;
ClientContext context;
Status status = stub_->SayHello(&context, request, &reply);
if (status.ok())
{
return reply.message();
}
else
{
std::cout << status.error_code() << ": " << status.error_message()<< std::endl;
return "RPC failed";
}
}
std::string Test(const std::string &user)
{
ClientContext context;
PlayStartReq req;
PlayStartRes res;
req.set_sessionid(10);
req.set_elestmname("BStar");
Status status = stub_->PlayStart(&context, req, &res);
if (status.ok())
{
std::cout << "result:" << res.result() << std::endl;
return res.extension();
}
else
{
std::cout << status.error_code() << ": " << status.error_message()<< std::endl;
return "RPC failed";
}
}
private:
std::unique_ptr<Greeter::Stub> stub_;
};
主要是定义两个方法用来发送grpc请求以及接收grpc响应
同样在实现方法的时候可以通过 request 结构里面的 set_ + 成员名 函数设置成员
message PlayStartReq { uint32 sessionid = 1;
string eleStmName = 2; }
PlayStartReq req; req.set_sessionid(10); req.set_elestmname("BStar");
同时通过 request 结构里面的成员名函数获取改成员
message PlayStartRes{ int32 result = 1; string extension = 2; } PlayStartRes res; std::cout << "result:" << res.result() << std::endl; 创建通道 定义客户端的时候初始化通道
//定义服务端口和地址 std::string target_str = "localhost:50051"; //创建通道 GreeterClient greeter(grpc::CreateChannel(target_str, grpc::InsecureChannelCredentials())); std::string user("world"); //std::string reply = greeter.SayHello(user); //发送请求 std::string reply = greeter.Test(user); std::cout << "Greeter received: " << reply << std::endl;
完整代码
#include <iostream>
#include <memory>
#include <string>
#include <grpcpp/grpcpp.h>
#include "player.grpc.pb.h"
using grpc::Channel;
using grpc::ClientContext;
using grpc::Status;
using Player::Greeter;
using Player::HelloReply;
using Player::HelloRequest;
using Player::PlayStartReq;
using Player::PlayStartRes;
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)
{
HelloRequest request;
request.set_name(user);
request.set_test("Greeter test");
HelloReply reply;
ClientContext context;
Status status = stub_->SayHello(&context, request, &reply);
if (status.ok())
{
return reply.message();
}
else
{
std::cout << status.error_code() << ": " << status.error_message()
<< std::endl;
return "RPC failed";
}
}
std::string Test(const std::string &user)
{
ClientContext context;
PlayStartReq req;
PlayStartRes res;
req.set_sessionid(10);
req.set_elestmname(user);
Status status = stub_->PlayStart(&context, req, &res);
if (status.ok())
{
std::cout << "result:" << res.result() << std::endl;
return res.extension();
}
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)
{
//定义服务端口和地址
std::string target_str = "localhost:50051";
std::string reply;
//创建通道
GreeterClient greeter(grpc::CreateChannel(target_str, grpc::InsecureChannelCredentials()));
std::string user("world");
reply = greeter.SayHello(user);
std::cout << "Greeter received: " << reply << std::endl;
//发送请求
reply = greeter.Test(user);
std::cout << "Greeter received: " << reply << std::endl;
return 0;
}
更多推荐

所有评论(0)