使用c++如何实现在gRPC中传输文件

使用c++实现gRPC远程调用框架中传输文件,proto文件如下:

syntax = "proto3";
package transferfile;
service TransferFile {
    rpc Upload(stream Chunk) returns (Reply) {}
}
message Chunk {
    bytes buffer = 1;
}
message Reply {
    int32 length = 1;
}

对应的c++代码如下:

client端:

#include <iostream>
#include <string>
#include <fstream>
#include <sys/time.h>
#include <grpc/grpc.h>
#include <grpc++/channel.h>
#include <grpc++/client_context.h>
#include <grpc++/create_channel.h>
#include <grpc++/security/credentials.h>
#include "transfer_file.grpc.pb.h"
using grpc::Channel;
using grpc::ClientContext;
using grpc::ClientWriter;
using grpc::Status;
using transferfile::Chunk;
using transferfile::Reply;
using transferfile::TransferFile;
#define CHUNK_SIZE 1024 * 1024
class TransferFileClient { public: TransferFileClient(std::shared_ptr<Channel> channel) : stub_(TransferFile::NewStub(channel)){}; void Upload();
private: std::unique_ptr<TransferFile::Stub> stub_; }; void TransferFileClient::Upload() { Chunk chunk; char data[CHUNK_SIZE]; Reply stats; ClientContext context; const char *filename = "./large_file_in"; std::ifstream infile; int len = 0; struct timeval start, end; gettimeofday(&start, NULL); infile.open(filename, std::ifstream::in | std::ifstream::binary); std::unique_ptr<ClientWriter<Chunk>> writer(stub_->Upload(&context, &stats)); while (!infile.eof()) { infile.read(data, CHUNK_SIZE); chunk.set_buffer(data, infile.gcount()); if (!writer->Write(chunk)) { // Broken stream. break; } len += infile.gcount(); } writer->WritesDone(); Status status = writer->Finish(); if (status.ok()) { gettimeofday(&end, NULL); std::cout << (end.tv_sec-start.tv_sec)+ (double)(end.tv_usec-start.tv_usec)/1000000 << std::endl; } else { std::cout << "TransferFile rpc failed." << std::endl; } }
int main(int argc, char** argv){ TransferFileClient guide(grpc::CreateChannel("localhost:10000", grpc::InsecureChannelCredentials())); guide.Upload(); return 0; }

server端:

#include <iostream>
#include <fstream>
#include <string>
#include <grpc/grpc.h>
#include <grpc++/server.h>
#include <grpc++/server_builder.h>
#include <grpc++/server_context.h>
#include <grpc++/security/server_credentials.h>
#include "transfer_file.grpc.pb.h"
using grpc::Server;
using grpc::ServerBuilder;
using grpc::ServerContext;
using grpc::ServerReader;
using grpc::Status;
using transferfile::Chunk;
using transferfile::Reply;
using transferfile::TransferFile;
#define CHUNK_SIZE 1024 * 1024

class TransferFileImpl final : public TransferFile::Service {
public:
    Status Upload(ServerContext* context, ServerReader<Chunk>* reader, Reply* reply);
};

Status TransferFileImpl::Upload(ServerContext* context, ServerReader<Chunk>* reader, Reply* reply) {
    Chunk chunk;
    const char *filename = "./server_tmp";
    std::ofstream outfile;
    const char *data;
outfile.open(filename, std::ofstream::
out | std::ofstream::trunc | std::ofstream::binary); while (reader->Read(&chunk)) { data = chunk.buffer().c_str(); outfile.write(data, chunk.buffer().length()); } long pos = outfile.tellp(); reply->set_length(pos); outfile.close(); return Status::OK; } void RunServer() { std::string server_address("0.0.0.0:50051"); TransferFileImpl 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; }

 

posted @ 2019-04-19 20:04  行木辛  阅读(6837)  评论(0编辑  收藏  举报