On Thu, 6 Oct 2011 01:00:37 -0700 (PDT)
yorick <[email protected]> wrote:

> I have now for the Java (this is unchanged) :
> ----------------------------------
> IRobotData data = getRobotData();
> System.out.println("phi:"+data.getPhi()+",
> distance:"+data.getDistance());
> int serDataSize = data.getSerializedSize();
> System.out.println("serDataSize:"+serDataSize);
> cos.writeRawVarint32(serDataSize);
> data.writeTo(cos);
> cos.flush();
> oos.flush();

Based on the existence of the line "oos.flush()", you're still using
ObjectOutputStream. Why? Get rid of it!

Also, you seem to be confused about the nature of TCP. In your Java
code, you're sending a varint32 followed by an encoded IRobotData. In
your C++, you're only calling recv() once, then building a
CodedInputStream over it, trying to parse a varint32, and then calling
recv() again and expecting to see the IRobotData message at that point.
TCP is a byte stream. It is NOT a message stream. You will much more
likely see recv() return the varint32 and the IRobotData in a single
call. It's possible, though, depending on the network, that it could do
anything: theoretically, it could return a single byte on each call,
though that's highly unlikely. You can't just expect to send a block of
bytes, e.g., a varint32, and expect the same block to come out the
other side. Notice that your C++ code is reading 4 bytes and then 21
bytes, while your Java code is (except for the OOS bug) writing a varint
plus 18 bytes. The first four bytes are probably from the
ObjectOutputStream, the next 3 might be the varint, or a mixture of the
ObjectOutputStream header and the varint, and the last 18 are probably
the encoded data.

Your previous code was OK because you read everything until EOF into an
std::string, then parsed from there. That works if you're OK waiting
until the connection is closed to parse things. If you want to parse
data as it arrives, you need to loop until enough data is received,
then parse it. It might be easier to use a fixed-size header rather
than a varint to mark the length of an individual message (a uint32
would be suitable). Starting from the beginning, you would then loop,
accumulating data, until you had 4 bytes, then turn those into the
uint32 indicating how big the rest of the message was. You would then
loop again, accumulating data, until you had that many bytes. Then you
could parse the message. If you call recv() with a separate buffer,
like you're doing here with "buf" and "sizeof(buf)", you may find it
returns more data than you actually expect, e.g., while you're
receiving the 4 bytes that make up your uint32, you might actually get,
say, 20 bytes. You need to keep the remaining 16, because they're part
of the following message. The alternative is to only receive as much as
you're willing to deal with in one go, so call recv() with 4 for your
uint32, then if you receive 3 bytes call recv() again with 1, until you
have your uint32, then similarly for receiving the full message.

Finally, there's no reason to NUL-terminate your buffers. You construct
a CodedInputStream and pass it recvSize, so the NUL is meaningless
(even if you didn't it would be meaningless, as there can be NULs in
the middle of encoded data).

Chris

-- 
You received this message because you are subscribed to the Google Groups 
"Protocol Buffers" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/protobuf?hl=en.

Reply via email to