grpc的proto消息体中嵌套流类型数据

        文档资源已上传:下载文档

        grpc时间管理系统

        grpc之AsyncNext:获取完全队列中的请求/响应

        一篇文章学会grpc编程,全网最详细,最全面保姆级教学

        c++实现gRPC

        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;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

迷茫的蜉蝣

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值