sending a message over TCP from a C++ client to a Java server

3,117 views
Skip to first unread message

Paul

unread,
Oct 13, 2010, 3:13:14 PM10/13/10
to Protocol Buffers
Hi,

I am new to protocol buffers, and I am trying to send a protocol
buffers message over TCP from a client computer running C++ to a
server computer running Java. Both computers are 64 bit.

On the server side (in Java), I open a ServerSocket on a port, and get
a Socket after accepting the client's connection. From the client
Socket (liveSock), I get an inputstream, which I pass to the handle
function, which calls parseDelimitedFrom on the inputstream.

On the client side (in C++), I open a TCP socket connection on the
same port with the server's IP address. I serialize the message using
SerializeToCodedStream into an array using ArrayOutputStream. After
serializing it, I send it over the TCP connection using my sendTCP
method which uses C++ sockets.

When I start running the two sides, the connection gets established.
However, when the client tries to send the data over TCP, the server
handle code crashes at parseDelimitedFrom with an
InvalideProtocolBufferException saying that the Message is missing
required fields.

I'm sure that my C++ TCP sockets work correctly, because I was able to
send text from C++ to Java without any problems. If it helps, I can
also post the TCP code I have.

I am not sure what I am doing wrong. I don't know if I am doing
things correctly on the server (Java) side. Please let me know if you
see any problems! Thanks a lot!

Paul



SERVER SIDE CODE:

ServerSocket sock = new ServerSocket(7003);

Socket liveSock = sock.accept();

handle(liveSock.getInputStream(), liveSock.getOutputStream()); //
handle defined below



HANDLE METHOD:

*** the protocol buffers message is called Snapshot ***

public static void handle(InputStream in, OutputStream output) {
try {
Snapshot snapshot = Snapshot.parseDelimitedFrom(in);
while(snapshot != null) {
System.out.println("SNAPSHOT: " + snapshot.getId()
snapshot = Snapshot.parseDelimitedFrom(in);
}
}
catch (IOException e) {
System.out.println("exception");
}
}



CLIENT SIDE CODE:

*** the protocol buffers message is called snap1 ***

int sock = openSocketClientTCP("127.100.100.100", 7003);

char snap_buf2[snap1.ByteSize()+1];

ZeroCopyOutputStream* raw_output = new
ArrayOutputStream(snap_buf2,snap1.ByteSize()+1);
CodedOutputStream* coded_output = new CodedOutputStream(raw_output);

coded_output->WriteVarint64(snap1.ByteSize());
snap1.SerializeToCodedStream(coded_output);

delete coded_output;
delete raw_output;

sendTCP(sock, snap_buf2, snap1.ByteSize() + 1);



Evan Jones

unread,
Oct 13, 2010, 3:56:16 PM10/13/10
to Paul, Protocol Buffers
On Oct 13, 2010, at 15:13 , Paul wrote:
> On the client side (in C++), I open a TCP socket connection on the
> same port with the server's IP address. I serialize the message using
> SerializeToCodedStream into an array using ArrayOutputStream. After
> serializing it, I send it over the TCP connection using my sendTCP
> method which uses C++ sockets.

SerializeToCodedStream does *not* prepend the message size. The Java
side is expecting that the message will start with the message length,
so that is probably why you are getting parse errors. You need to do
something like:


codedOutput.WriteVarint32(msg.ByteSize());
msg.SerializeToCodedStream(codedOutput);
codedOutput.flush();

...


Hope this helps,

Evan

(as an aside: the C++ API really should have an equivalent to
writeDelimitedTo and parseDelimited on the Java side).

--
Evan Jones
http://evanjones.ca/

Paul

unread,
Oct 13, 2010, 4:49:34 PM10/13/10
to Protocol Buffers
Thanks for the suggestion. However, I am already prepending the
message size on the C++ side in the line:
coded_output->WriteVarint64(snap1.ByteSize());

is there anything else that stands out to you?

thanks for any further help.

Evan Jones

unread,
Oct 13, 2010, 5:20:25 PM10/13/10
to Paul, Protocol Buffers
On Oct 13, 2010, at 16:49 , Paul wrote:
> Thanks for the suggestion. However, I am already prepending the
> message size on the C++ side in the line:
> coded_output->WriteVarint64(snap1.ByteSize());

You may want to verify that the exact bytes that come out of
msg.SerializeToString (or related) are coming out the other end and
getting passed into parseDelimited. It might be helpful if you sent a
snippet of code where you are sending and receiving the messages, but
I can't think of anything off the top of my head.

Evan

Paul

unread,
Oct 13, 2010, 8:09:02 PM10/13/10
to Protocol Buffers
ok thanks a lot! I ended up finding that my TCP send function was not
set up correctly. Once that was fixed, it worked fine. Thanks!

Robert Abadi

unread,
Mar 2, 2012, 10:20:22 AM3/2/12
to prot...@googlegroups.com

I am new in java networking programming and also in protocol buffers.
If the client side is also run in Java.
How to send the message?
thank you for your help.

Robert Abadi


Reply all
Reply to author
Forward
0 new messages