3

I am having a lot of trouble with GRPC when using byte array. This is by .proto

message myType {
    int32 format = 1;
    bytes data = 2;
}

I am using CPP for Server implementation and Java for Client. Using ByteString in Java is a breeze but cannot deserialize in CPP (byte[] being changed from what was being sent from Java).

buffer is a byte[] byte buffer[<large_size>] And I'm converting the byte array (it's an image) into a smaller byte array, and it's crashing when trying to convert the byte[] received from grpc. The conversion function in CPP is good as I used it with the same image before using GRPC

This is the deserialization code for CPP. Here "req" is a myType object, and buffer is a byte[]

myFormat = req->format();
dataLen = req->data().length();
memcpy(buffer, req->data().c_str(), dataLen);

From what I understand, req->data() is in cpp std::string format

d1xlord
  • 239
  • 3
  • 4
  • 12
  • 2
    What does *"cannot deserialize successfully"* mean? What happens? Post any errors, crashes + stacktraces, expected output vs received output or however else the "failure" manifests itself – UnholySheep Jul 05 '17 at 12:53
  • Getting wrong/invalid data in the buffer byte array – d1xlord Jul 05 '17 at 12:55
  • 2
    You need to provide a [mcve] (e.g.: it's unclear how `buffer` is allocated and how you are checking the data you receive) – UnholySheep Jul 05 '17 at 12:57
  • buffer is a byte[] `byte buffer[]` And I'm converting the byte array (it's an image) into a smaller byte array, and it's crashing when trying to convert the byte[] received from grpc. The conversion function in CPP is good as I used it with the same image before using GRPC – d1xlord Jul 05 '17 at 13:00

2 Answers2

2

On the client side, you should pass both the parameter and its length. parameter.set_framemat(mat, 12);

Truong Do
  • 29
  • 2
0

Do check if the length of the array at the server side is not zero. Note that bytes is char array and grpc is de marshalling it as string. So if say the array is filled with null characters the data length comes as zero.

I was trying a similar use case

Proto file

message Parameters {
      bytes framemat = 16; 
};

Client Snippet

const char mat[12] = {0}
parameter.set_framemat(mat);
stream->Write(parameter);

Server Snippet

std::thread reader([&]() {

    ::nokia::nas::Parameters request;
    while (stream->Read(&request))
    {
      //get the params
       grpc::string mat = request.framemat();
      logger->info(" Length of Bytes= {} , mat.length()}

Output was zero! So I changed the client input to check with some char strings and sure enough the data length was coming as 4 at the server side; because this time it was a valid string and string length matched.

const char mat[12] = "sdsd";

Better way is to specify in the proto the data as well as the data length

message StreamBytes { 
  bytes data_bytes =1;
  int32 data_length = 2;
};
Alex Punnen
  • 5,287
  • 3
  • 59
  • 71
  • actually if I zero fill the array and send, it is not really getting send; If the first char is non zero then it works mat[0] ='A'; -> ok mat[1] = 'B'; -> not ok ;does not get transferred if mat is zero initialised - https://stackoverflow.com/questions/531477/strange-assembly-from-array-0-initialization/531490 (strange) – Alex Punnen Sep 12 '17 at 08:31