How to send byte data over gRPC in C++?

30 views
Skip to first unread message

Joseph Liu

unread,
Dec 3, 2020, 10:59:05 AM12/3/20
to grpc.io
So I'm using gRPC to store data in a key-value store.

The protos look like this:

    syntax = "proto3";
    
    package keyvaluestore;
    
    service KeyValueStore {
      rpc AddUser(Credentials) returns (Response) {}
      rpc Get(Request) returns (Response) {}
      rpc Put(Request) returns (Response) {}
      rpc Cput(Request) returns (Response) {}
      rpc Delete(Request) returns (Response) {}
    }
    
    message Credentials {
      string user = 1;
      string passwd = 2;
    }
    
    message Request {
      string user = 1;
      string key = 2;
      bytes val = 3;
      bytes val2 = 4;
      string addr = 5;
    }
    
    message Response {
      bytes val = 1;
      uint32 nbytes = 2;
      string message = 3;
    }

Right now, the issue is that if we send over say, an image as byte data which can include the null byte, then when the server receives it in the `Request` object, it treats it as a string; when it does this it only reads it up the the first null byte.

How we pack the `Request` object on the client side:

    bool KeyValueStoreClient::Put(const string& user, const string& key, const char* val) {
      Request req;
      req.set_user(user);
      req.set_key(key);
      req.set_val(val);
    
      ClientContext ctx;
      Response res;
      Status status = stub_->Put(&ctx, req, &res);
    }

Server receives `req->val()` as a string instead of `char*`:

    Status KeyValueStoreServiceImpl::Put(ServerContext* ctx, const Request* req, Response* res) {
      // req->val() is a string
    
    }




tobias.krueger

unread,
Dec 3, 2020, 11:04:02 AM12/3/20
to grpc.io
The std::string, which is used as the container for the grpc datatype "bytes", can handle embedded nul bytes.
But In your "Put" method you pass the parameter "val" as char * pointer.
This char * pointer will be converted to a std::string terminating with the first occurrence of the nul byte.

So must either past the value "val" as std::string or std::vector<char> 

HTH
Tobias

Joseph Liu

unread,
Dec 3, 2020, 11:10:49 AM12/3/20
to grpc.io
So basically, send val as a string, and even when we receive it on the server side, I can store it in my key-value store as a string too? (Right now I'm storing it as a char*)

tobias.krueger

unread,
Dec 3, 2020, 11:17:08 AM12/3/20
to grpc.io
>   I can store it in my key-value store as a string too 

It is hard to tell as we know nothing about your store.
A char pointer is just an address into your memory. It has no information about the size of the block.
If you interpret this pointer as a character string, the convention is that this string ends with the very first nul byte.
If it is the address a blob, no one can tell how long it is.
But this actually has nothing to do the with GRPC - this is very basic string/memory handling of C++

Joseph Liu

unread,
Dec 3, 2020, 11:29:20 AM12/3/20
to grpc.io
Ok got it, it seems to me the best way is to just treat is as a string because std::string can handle embedded nul bytes. Thanks!
Reply all
Reply to author
Forward
0 new messages