2

I am trying to send some simple messages from c++ to c# and visa versa but i m missing something...

c++ code to serialize a sample message:

std::string data;

SampleHello hello;
hello.set_name("Hello");
hello.Set_num(12);
hello.SerializeToString(&data);

c# receive

SampleHello.Parser.ParseFrom(buffer)

And I 'm receiving

Google.Protobuf.InvalidProtocolBufferException: Protocol message contained an invalid tag (zero).

I don't know if i m missing something completely by this seems so simple and yet...anyway I ve tried several other solutions to no avail, like using the solution from C# Google.ProtocolBuffers Deserialization Method (proto3)

T.Zak
  • 309
  • 2
  • 14
  • does it work? (I'm unclear) – Marc Gravell May 10 '18 at 11:56
  • ops srr in my haste i forgot to add the error msg, I m receiving Google.Protobuf.InvalidProtocolBufferException: Protocol message contained an invalid tag (zero). – T.Zak May 10 '18 at 12:10
  • ah, right; now we're talking; how did you get the size of `data`? is it possible that the buffer was over-allocated, and will contain trailing space? If you have a dump of what `buffer` contains (hex, base-64, whatever), I can probably tell you – Marc Gravell May 10 '18 at 12:12
  • session->Send(data.c_str(), sizeof(data.c_str())); and the session sends it via its stored socket I send 0A 0C 48 65 6C 6C 6F 20 and receive 0A 0C 48 65 6C 6C 6F 20 – T.Zak May 10 '18 at 12:46

2 Answers2

1

0A 0C 48 65 6C 6C 6F 20

Yeah, there's something very wrong in that data; 0A means "field 1, length prefixed"; 0C means 12 bytes ... and you only have another 6 bytes of data; the next 5 are "Hello"; since we're still missing 7 bytes from field 1, the 20 could be a space, which might make sense if this was actually "Hello world!" ? And we haven't even touched the num / 12, which will need another few bytes.

I'm guessing you didn't allocate a big enough buffer. I'm guessing there's an API somewhere alongside SerializeToString to tell you how many bytes you need for the buffer.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
0

After a lot of wasted time due to not knowing c++ very well and after a venture into different solutions like gRPC... I have finally found a working solution.

The problem was in the c++ side where some character was appended when i was trying to send the message.c_str() directly via the socket.

working solution for sending a simple protobuf message in c++:

std::string data;

SampleHello hello;
hello.set_name("Hello");
hello.set_num(12); 
hello.SerializeToString(&data);

char messageToBeSent[data.length()];

sprintf(messageToBeSent, "%s", data);

//simply sends via the socket using write(mSocket, msgToBeSent, msgSize);
session->send(messageToBeSent,sizeof(messageToBeSent));

In case you re like me and instead of using the sane approach of using boost network streams, you implemented your own circular buffer without using ostream. This is how you can receive a message

#include "google/protobuf/io/zero_copy_stream_impl_lite.h"

typedef google::protobuf::io::ArrayInputStream arrayIStream;

void HandlePacket(int packetSize)
{
   char* packet = newchar[packetSize];  //allocate some space for the message
   rcvBuffer.Read(packet,packetSize); //the buffer where our received messages are
   arrayIStream arr(rcvBuffer.GetBuffer(), packetSize);   //pass the received message to a zero coded input object so we can use the delimited functions

   HeaderProto header;    //the header as described in the .proto file
   if (readDelimitedFrom(&arr,&header)) //readDelimitedFrom is the c++ solution as provided from the author of the c++ lib (look below for link)
   {
      //Do stuff with your message
   }
   delete packet;
}

readDelimitedFrom solution

T.Zak
  • 309
  • 2
  • 14