文档资源已上传:下载文档
stream流类型在grpc的实际项目中是出现频率很高的数据类型,一般是位于交互参数或者返回值的位置:
rpc Get_Stream(request) returns(stream response){}//获取数据流
rpc Put_Stream(stream request) returns(response){}//发送数据流
但是如果想要获取的消息体只有一部分是流数据该怎么办呢?
//例如获取某个班级的学生信息:
//学生信息
message Stu{
string name = 1;
sint32 age = 2;
}
//班级信息
message Msg{
//班级名称(几年级几班)
string classNum = 1;
//一个班级有好多学生,要用流的方式
//有可能你以为是:stream Stu student = 2;stream不用于消息体,一般使用repeated
repeated Stu student = 2;
}
repeated类型用于表示重复的数据集合。它类似于编程语言中的数组或列表,可以包含多个相同类型的元素。服务器与客户端进行数据传输的示例代码如下:
proto文件:
syntax = "proto3";
package repeated_test;
service Repeated{
rpc GetClassMsg(NullRequest) returns(Msg){}
rpc PutClassMsg(Msg) returns(NullResponse){}
}
message NullRequest{}
message NullResponse{}
message Stu{
string name = 1;
sint32 age = 2;
}
//班级信息
message Msg{
string classNum = 1;
repeated Stu student = 2;
}
server.cpp
#include <grpcpp/grpcpp.h>
#include <iostream>
#include "repeated.grpc.pb.h"
#include "repeated.pb.h"
using grpc::Server;
using grpc::ServerBuilder;
using grpc::ServerContext;
using grpc::ServerReader;
using grpc::ServerWriter;
using grpc::Status;
using grpc::StatusCode;
using namespace repeated_test;
class RepeatedService final : public repeated_test::Repeated::Service
{
public:
Status GetClassMsg(ServerContext *context, const NullRequest *request, Msg *response)
{
response->set_classnum("class_1_2");
//添加学生信息
Stu *stu1 = response->add_student();
stu1->set_age(10);
stu1->set_name("tom");
Stu *stu2 = response->add_student();
stu2->set_age(11);
stu2->set_name("jerry");
return Status::OK;
}
Status PutClassMsg(ServerContext *context, const Msg *request, NullResponse *response)
{
std::string classNum = request->classnum();
for (const Stu &stu : request->student())
{
std::string name = stu.name();
int age = stu.age();
std::cout << "name : " << name << std::endl;
std::cout << "age : " << age << std::endl;
}
return Status::OK;
}
};
void RunServer()
{
std::string server_address("0.0.0.0:50051");
RepeatedService 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()
{
RunServer();
return 0;
}
client.cpp
#include <grpcpp/grpcpp.h>
#include <iostream>
#include "repeated.grpc.pb.h"
#include "repeated.pb.h"
using grpc::Channel;
using grpc::ClientContext;
using grpc::Status;
using repeated_test::Repeated;
using repeated_test::NullRequest;
using repeated_test::Msg;
using repeated_test::NullResponse;
using repeated_test::Stu;
class RepeatedClient {
public:
RepeatedClient(std::shared_ptr<Channel> channel)
: stub_(Repeated::NewStub(channel)) {}
// 定义 GetClassMsg RPC 调用的方法
void GetClassMsg() {
NullRequest request;
Msg response;
// 创建上下文和用于存储调用结果的 Response 对象
ClientContext context;
// 调用 GetClassMsg RPC
Status status = stub_->GetClassMsg(&context, request, &response);
// 处理调用结果
if (status.ok()) {
std::cout << "ClassNum: " << response.classnum() << std::endl;
for (const Stu& stu : response.student()) {
std::cout << "Student: " << stu.name() << " (Age: " << stu.age() << ")" << std::endl;
}
} else {
std::cout << "RPC failed with error code: " << status.error_code() << std::endl;
}
}
// 定义 PutClassMsg RPC 调用的方法
void PutClassMsg() {
Msg request;
NullResponse response;
// 设置班级信息
request.set_classnum("Class 2");
Stu* stu1 = request.add_student();
stu1->set_name("Tom");
stu1->set_age(22);
Stu* stu2 = request.add_student();
stu2->set_name("Jerry");
stu2->set_age(23);
// 创建上下文和用于存储调用结果的 Response 对象
ClientContext context;
// 调用 PutClassMsg RPC
Status status = stub_->PutClassMsg(&context, request, &response);
// 处理调用结果
if (status.ok()) {
std::cout << "PutClassMsg RPC succeeded" << std::endl;
} else {
std::cout << "RPC failed with error code: " << status.error_code() << std::endl;
}
}
private:
std::unique_ptr<Repeated::Stub> stub_;
};
int main() {
std::string server_address("192.168.0.196:50051");
// 创建 Channel
std::shared_ptr<Channel> channel = grpc::CreateChannel(server_address, grpc::InsecureChannelCredentials());
// 创建 RepeatedClient 对象
RepeatedClient client(channel);
// 调用 GetClassMsg RPC
std::cout << "Getting class message..." << std::endl;
client.GetClassMsg();
// 调用 PutClassMsg RPC
std::cout << "Putting class message..." << std::endl;
client.PutClassMsg();
return 0;
}