grpc c++流式传输demo

目录结构

 

 编译脚本build.sh

if [ -d "./proto_code" ];then
    rm -rf ./proto_code
fi
mkdir ./proto_code
protoc -I ./ --grpc_out=./proto_code --plugin=protoc-gen-grpc=`which grpc_cpp_plugin` ./reduce.proto
protoc -I ./ --cpp_out=./proto_code ./reduce.proto

if [ -d "./build" ];then
    rm -rf ./build
fi
mkdir ./build
cd build
cmake ..
make
cd ..

CMakeLists.txt

cmake_minimum_required(VERSION 3.5)
project(test2)
find_package(Threads REQUIRED)
find_package(Protobuf REQUIRED)
set(_PROTOBUF_LIBPROTOBUF protobuf::libprotobuf)
set(_REFLECTION gRPC::grpc++_reflection)
find_package(gRPC CONFIG REQUIRED)
set(_GRPC_GRPCPP gRPC::grpc++)

SET(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} "-pthread")


include_directories("${CMAKE_CURRENT_BINARY_DIR}/../proto_code")
set(hw_proto_srcs "${CMAKE_CURRENT_BINARY_DIR}/../proto_code/reduce.pb.cc")
set(hw_proto_hdrs "${CMAKE_CURRENT_BINARY_DIR}/../proto_code/reduce.pb.h")
set(hw_grpc_srcs "${CMAKE_CURRENT_BINARY_DIR}/../proto_code/reduce.grpc.pb.cc")
set(hw_grpc_hdrs "${CMAKE_CURRENT_BINARY_DIR}/../proto_code/reduce.grpc.pb.h")
# hw_grpc_proto
add_library(hw_grpc_proto
  ${hw_grpc_srcs}
  ${hw_grpc_hdrs}
  ${hw_proto_srcs}
  ${hw_proto_hdrs})
target_link_libraries(hw_grpc_proto
  ${_REFLECTION}
  ${_GRPC_GRPCPP}
  ${_PROTOBUF_LIBPROTOBUF})

# Targets greeter_[async_](client|server)
foreach(_target
  reduce_server reduce_client)
  add_executable(${_target} "${_target}.cc")
  target_link_libraries(${_target}
    hw_grpc_proto
    ${_REFLECTION}
    ${_GRPC_GRPCPP}
    ${_PROTOBUF_LIBPROTOBUF})
endforeach()

proto文件

syntax="proto3";

option java_multiple_files=true;
option java_package="io.grpc.example.reduce";
option java_outer_classname="ReduceProto";
option objc_class_prefix="RDC";

package reduce;

service ReduceService{
    rpc getData(stream Data) returns(stream Data){}
}

message Data{
    int32 data=1;
}

服务端代码

#include <iostream>
#include <string>
#include <memory>
#include <pthread.h>
#include <unistd.h>
#include <vector>

#include <grpc/grpc.h>
#include <grpcpp/security/server_credentials.h>
#include <grpcpp/server.h>
#include <grpcpp/server_builder.h>
#include <grpcpp/server_context.h>
#include "./proto_code/reduce.grpc.pb.h"

using std::cout;
using std::endl;
using std::string;
using std::unique_ptr;
using std::shared_ptr;
using std::vector;

using grpc::Server;
using grpc::ServerBuilder;
using grpc::ServerContext;
using grpc::ServerReader;
using grpc::ServerWriter;
using grpc::ServerReaderWriter;
using grpc::Status;

using reduce::Data;
using reduce::ReduceService;

class ReduceImpl final: public ReduceService::Service{
public:
    Status getData(ServerContext* context,ServerReaderWriter<Data,Data>* stream)override
    {
        Data read_data;
        while(stream->Read(&read_data))
        {
            pthread_mutex_lock(&mu_);
            received_data.push_back(read_data);
            cout<<"receive data: "<<read_data.data()<<endl;
            pthread_mutex_unlock(&mu_);
        }
        for(const Data& n:received_data)
        {
            stream->Write(n);
            cout<<"=====write "<<n.data()<<endl;
        }
        return Status::OK;
    }
private:
    pthread_mutex_t mu_=PTHREAD_MUTEX_INITIALIZER;
    vector<Data> received_data;
};

void RunServer()
{
    string server_addr("0.0.0.0:50051");
    ReduceImpl service;
    ServerBuilder builder;
    builder.AddListeningPort(server_addr,grpc::InsecureServerCredentials());
    builder.RegisterService(&service);
    unique_ptr<Server> server(builder.BuildAndStart());
    cout<<"Server listening on "<<server_addr<<endl;
    server->Wait();
}

int main(int argc,char** argv)
{
    RunServer();
    return 0;
}

客户端代码

#include <iostream>
#include <memory>
#include <string>
#include <pthread.h>
#include <unistd.h>
#include <thread>
#include <vector>

#include <grpc/grpc.h>
#include <grpcpp/channel.h>
#include <grpcpp/client_context.h>
#include <grpcpp/create_channel.h>
#include <grpcpp/security/credentials.h>
#include "./proto_code/reduce.grpc.pb.h"

using std::cout;
using std::endl;
using std::string;

using grpc::Channel;
using grpc::ClientContext;
using grpc::ClientReader;
using grpc::ClientWriter;
using grpc::ClientReaderWriter;
using grpc::Status;

using reduce::Data;
using reduce::ReduceService;

class ReduceClient{
public:
    ReduceClient(std::shared_ptr<Channel> channel):stub_(ReduceService::NewStub(channel)){}
    void sendData()
    {
        ClientContext context;
        std::shared_ptr<ClientReaderWriter<Data,Data>> stream(stub_->getData(&context));

        auto thread_func=[stream](){
            std::vector<Data> v_tmp;
            for(int i=0;i<50;++i)
            {
                Data tmp;
                tmp.set_data(i);
                v_tmp.push_back(tmp);
            }
            for(Data& d:v_tmp)
            {
                std::cout<<"write"<<std::endl;
                stream->Write(d);
            }
            stream->WritesDone();
        };
        //pthread_create(&client_send_thread,NULL,(void* (*)(void*))&thread_func,NULL);
        std::thread writer(thread_func);
        
        Data recv_data;
        while(stream->Read(&recv_data))
        {
            std::cout<<"data "<<recv_data.data()<<" send success"<<std::endl;
        }
        writer.join();

        Status status=stream->Finish();
        if(!status.ok())
        {
            std::cout<<"getData rpc failed"<<std::endl;
        }
    }
private:
    std::unique_ptr<ReduceService::Stub> stub_;
    pthread_t client_send_thread;
};

int main(int argc,char** argv)
{
    ReduceClient client1(grpc::CreateChannel("localhost:50051",grpc::InsecureChannelCredentials()));
    client1.sendData();
    return 0;
}

流式传输使用stream,stream中有Read和Write,客户端和服务端都要调用Read和Write

目前的问题是没办法写成死循环,就是一直发送数据。一旦写成死循环就会报这个错

E0323 16:50:21.462651883 1254646 call_op_set.h:985] assertion failed: false
Aborted (core dumped)

然后core就dump了

 

posted @ 2022-03-23 17:20  Wangtn  阅读(2155)  评论(0编辑  收藏  举报