У меня возникла проблема с запросом const с буферами протокола google, использующими grpc. Вот моя проблема:Как создать модификацию на месте массива с использованием буферов протокола grpc и google?
Я хотел бы сделать внутреннюю модификацию значения массива. Для этого я написал этот простой пример, где я пытаюсь передать массив и суммировать все его содержимое. Вот мой код:
adder.proto:
syntax = "proto3";
option java_package = "io.grpc.examples";
package adder;
// The greeter service definition.
service Adder {
// Sends a greeting
rpc Add (AdderRequest) returns (AdderReply) {}
}
// The request message containing the user's name.
message AdderRequest {
repeated int32 values = 1;
}
// The response message containing the greetings
message AdderReply {
int32 sum = 1;
}
server.cc:
//
// Created by Eric Reis on 7/6/16.
//
#include <iostream>
#include <grpc++/grpc++.h>
#include "adder.grpc.pb.h"
class AdderImpl final : public adder::Adder::Service
{
public:
grpc::Status Add(grpc::ServerContext* context, const adder::AdderRequest* request,
adder::AdderReply* reply) override
{
int sum = 0;
for(int i = 0, sz = request->values_size(); i < sz; i++)
{
request->set_values(i, 10); // -> this gives an error caused by the const declaration of the request variable
// error: "Non-const function 'set_values' is called on the const object"
sum += request->values(i); // -> this works fine
}
reply->set_sum(sum);
return grpc::Status::OK;
}
};
void RunServer()
{
std::string server_address("0.0.0.0:50051");
AdderImpl service;
grpc::ServerBuilder builder;
// Listen on the given address without any authentication mechanism.
builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());
// Register "service" as the instance through which we'll communicate with
// clients. In this case it corresponds to an *synchronous* service.
builder.RegisterService(&service);
// Finally assemble the server.
std::unique_ptr<grpc::Server> server(builder.BuildAndStart());
std::cout << "Server listening on " << server_address << std::endl;
// Wait for the server to shutdown. Note that some other thread must be
// responsible for shutting down the server for this call to ever return.
server->Wait();
}
int main(int argc, char** argv)
{
RunServer();
return 0;
}
client.cc:
//
// Created by Eric Reis on 7/6/16.
//
#include <iostream>
#include <grpc++/grpc++.h>
#include "adder.grpc.pb.h"
class AdderClient
{
public:
AdderClient(std::shared_ptr<grpc::Channel> channel) : stub_(adder::Adder::NewStub(channel)) {}
int Add(int* values, int sz) {
// Data we are sending to the server.
adder::AdderRequest request;
for (int i = 0; i < sz; i++)
{
request.add_values(values[i]);
}
// Container for the data we expect from the server.
adder::AdderReply reply;
// Context for the client. It could be used to convey extra information to
// the server and/or tweak certain RPC behaviors.
grpc::ClientContext context;
// The actual RPC.
grpc::Status status = stub_->Add(&context, request, &reply);
// Act upon its status.
if (status.ok())
{
return reply.sum();
}
else {
std::cout << "RPC failed" << std::endl;
return -1;
}
}
private:
std::unique_ptr<adder::Adder::Stub> stub_;
};
int main(int argc, char** argv) {
// Instantiate the client. It requires a channel, out of which the actual RPCs
// are created. This channel models a connection to an endpoint (in this case,
// localhost at port 50051). We indicate that the channel isn't authenticated
// (use of InsecureChannelCredentials()).
AdderClient adder(grpc::CreateChannel("localhost:50051",
grpc::InsecureChannelCredentials()));
int values[] = {1,2};
int sum = adder.Add(values, 2);
std::cout << "Adder received: " << sum << std::endl;
return 0;
}
Моя ошибка происходит, когда я пытаюсь вызвать метод set_values () объекта запроса, который определяется как const. Я понимаю, почему эта ошибка возникает, но я просто не могу понять, как ее преодолеть, не делая копию массива.
Я попытался удалить определение const, но вызовы RPC терпят неудачу, когда я это делаю.
Поскольку я новичок в этом мире RPC и даже больше на grpc и буферах протокола google, я бы хотел обратиться за помощью. Каков наилучший способ решить эту проблему?
Hi @asynchronos. Я думаю, что я понял вашу мысль, но я думаю, что я уже передаю копию на сервер (пожалуйста, исправьте меня, если я ошибаюсь) с линией 'stub _-> Add (& context, request, & reply);'. Дело в том, что я пытаюсь изменить значение массива на стороне сервера с помощью метода set_values (), но поскольку подпись метода Add делает запрос const, я не могу этого сделать. –
@Eric Почему вы хотите изменить значения массива на стороне сервера? Это ваше намерение передать измененный массив обратно клиенту? Сгенерированный код объявляет аргумент AdderRequest методу сервера 'const', потому что любые изменения не будут переданы клиенту обратно. – asynchronos
да, это именно то, что я хочу. Отправляйте массив клиенту, и я не хотел бы делать другую копию, потому что мой массив слишком большой, а с другой копией у меня, вероятно, закончится нехватка памяти (10^10 будет размером моего массива) –