Thanks for your response. I remove the ObjectOutputStream and I changed the way of reading the socket according what you said and it works !
I can now exchange data between Java and C++. Thank you ! :) On 6 oct, 23:21, Christopher Head <[email protected]> wrote: > 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.
