grpc实现客户端之间的文件传输C++代码完整示例
时间: 2023-07-12 10:03:58 浏览: 144
以下是一个简单的示例,展示了如何使用gRPC实现客户端之间的文件传输。在这个示例中,我们将使用C++来编写代码。
首先,我们需要定义一个.proto文件来指定我们的服务和消息。在我们的示例中,我们将定义一个名为FileTransfer的服务,其中包含两个方法:Upload和Download。Upload方法允许客户端将文件上传到服务器,而Download方法允许客户端从服务器下载文件。以下是.proto文件的示例:
```
syntax = "proto3";
package filetransfer;
service FileTransfer {
rpc Upload(UploadRequest) returns (UploadResponse) {}
rpc Download(DownloadRequest) returns (stream DownloadResponse) {}
}
message UploadRequest {
string filename = 1;
bytes content = 2;
}
message UploadResponse {
bool success = 1;
}
message DownloadRequest {
string filename = 1;
}
message DownloadResponse {
bytes content = 1;
}
```
在.proto文件中定义了我们的服务和消息之后,我们可以使用protoc工具来生成C++代码。我们可以使用以下命令生成C++代码:
```
protoc -I=./ --grpc_out=./ --plugin=protoc-gen-grpc=/usr/local/bin/grpc_cpp_plugin filetransfer.proto
protoc -I=./ --cpp_out=./ filetransfer.proto
```
这将在当前目录下生成filetransfer.grpc.pb.h和filetransfer.pb.h两个文件,分别用于gRPC和protobuf。
接下来,我们需要编写服务器端代码。以下是一个简单的服务器实现,它实现了Upload和Download方法:
```c++
#include <iostream>
#include <memory>
#include <string>
#include <fstream>
#include <grpc++/grpc++.h>
#include "filetransfer.grpc.pb.h"
using grpc::Server;
using grpc::ServerBuilder;
using grpc::ServerContext;
using grpc::Status;
using filetransfer::FileTransfer;
using filetransfer::UploadRequest;
using filetransfer::UploadResponse;
using filetransfer::DownloadRequest;
using filetransfer::DownloadResponse;
class FileTransferServiceImpl final : public FileTransfer::Service {
Status Upload(ServerContext* context, const UploadRequest* request,
UploadResponse* response) override {
std::ofstream outfile(request->filename(), std::ios::binary);
outfile.write(request->content().c_str(), request->content().length());
outfile.close();
response->set_success(true);
return Status::OK;
}
Status Download(ServerContext* context, const DownloadRequest* request,
grpc::ServerWriter<DownloadResponse>* writer) override {
std::ifstream infile(request->filename(), std::ios::binary);
if (!infile.is_open()) {
return Status(grpc::StatusCode::NOT_FOUND, "File not found");
}
char buffer[1024];
while (infile) {
infile.read(buffer, 1024);
DownloadResponse response;
response.set_content(buffer, infile.gcount());
writer->Write(response);
}
return Status::OK;
}
};
void RunServer() {
std::string server_address("0.0.0.0:50051");
FileTransferServiceImpl service;
grpc::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;
}
```
在这个例子中,我们定义了一个FileTransferServiceImpl类,它继承了我们在.proto文件中定义的FileTransfer::Service服务。在Upload方法中,我们从请求中获取文件名和内容,并将其写入文件。在Download方法中,我们打开请求文件以读取其内容,并将其写入响应流中。
最后,我们需要编写客户端代码。以下是一个简单的客户端实现,它演示了如何上传文件和下载文件:
```c++
#include <iostream>
#include <fstream>
#include <memory>
#include <string>
#include <grpc++/grpc++.h>
#include "filetransfer.grpc.pb.h"
using grpc::Channel;
using grpc::ClientContext;
using grpc::Status;
using filetransfer::FileTransfer;
using filetransfer::UploadRequest;
using filetransfer::UploadResponse;
using filetransfer::DownloadRequest;
using filetransfer::DownloadResponse;
class FileTransferClient {
public:
FileTransferClient(std::shared_ptr<Channel> channel)
: stub_(FileTransfer::NewStub(channel)) {}
bool UploadFile(const std::string& filename) {
std::ifstream infile(filename, std::ios::binary);
if (!infile.is_open()) {
std::cout << "File not found" << std::endl;
return false;
}
std::stringstream buffer;
buffer << infile.rdbuf();
UploadRequest request;
request.set_filename(filename);
request.set_content(buffer.str());
UploadResponse response;
ClientContext context;
Status status = stub_->Upload(&context, request, &response);
if (status.ok()) {
return response.success();
} else {
std::cout << "Error: " << status.error_code() << ": " << status.error_message() << std::endl;
return false;
}
}
bool DownloadFile(const std::string& filename) {
DownloadRequest request;
request.set_filename(filename);
ClientContext context;
std::unique_ptr<grpc::ClientReader<DownloadResponse>> reader(
stub_->Download(&context, request));
DownloadResponse response;
std::ofstream outfile(filename, std::ios::binary);
while (reader->Read(&response)) {
outfile.write(response.content().c_str(), response.content().length());
}
Status status = reader->Finish();
if (status.ok()) {
return true;
} else {
std::cout << "Error: " << status.error_code() << ": " << status.error_message() << std::endl;
return false;
}
}
private:
std::unique_ptr<FileTransfer::Stub> stub_;
};
int main(int argc, char** argv) {
FileTransferClient client(grpc::CreateChannel("localhost:50051", grpc::InsecureChannelCredentials()));
client.UploadFile("test.txt");
client.DownloadFile("test.txt");
return 0;
}
```
在这个例子中,我们定义了一个FileTransferClient类,它使用我们在.proto文件中定义的FileTransfer::Service服务。在UploadFile方法中,我们打开要上传的文件并将其读入一个字符串流中。然后,我们将文件名和内容作为请求发送到服务器,并等待响应。在DownloadFile方法中,我们向服务器发出下载文件的请求,并将响应流写入文件。最后,我们创建了一个FileTransferClient对象并调用其UploadFile和DownloadFile方法来上传和下载文件。
这就是一个简单的使用gRPC实现客户端之间文件传输的例子。请注意,这个例子只是一个起点,您可以根据您的需求和场景进行更改和扩展。
阅读全文