writing strings to sockets-- formatting gotchas?

J

Jim Bancroft

I'm writing out an integer to a socket using java. The client on the other
end is a plane-jane C program, and I'm having trouble figuring out why the
two of them won't talk properly.

I'm writing my integer using a DataOutputStream, like so:

String myString = Integer.toString(myInt);
DataOutputStrea, outp;

//....
outp.writeBytes(myString);


in the C client I'm doing this:

n = read(sockfd,mybuf,sizeof(mybuf));

....where mybuf is an unsigned char[16];

when it comes time to print the value I do this:

int newInt;
newInt = atoi(mybuf);

printf("the value is: %d\n", newInt);

But what happens is I get double values on the output. For instance, if the
java program has a value of "34" in myInt, the printf statement prints out
"3434". Same with every other integer I try.

I've looked at the mybuf array byte by byte and in fact, there are two
copies of my integer in there. Does anyone know what might be going on here
and what steps I can take to get C and Java to talk nice in this instance?
 
K

Knute Johnson

Jim said:
I'm writing out an integer to a socket using java. The client on the other
end is a plane-jane C program, and I'm having trouble figuring out why the
two of them won't talk properly.

I'm writing my integer using a DataOutputStream, like so:

String myString = Integer.toString(myInt);
DataOutputStrea, outp;

//....
outp.writeBytes(myString);


in the C client I'm doing this:

n = read(sockfd,mybuf,sizeof(mybuf));

...where mybuf is an unsigned char[16];

when it comes time to print the value I do this:

int newInt;
newInt = atoi(mybuf);

printf("the value is: %d\n", newInt);

But what happens is I get double values on the output. For instance, if the
java program has a value of "34" in myInt, the printf statement prints out
"3434". Same with every other integer I try.

I've looked at the mybuf array byte by byte and in fact, there are two
copies of my integer in there. Does anyone know what might be going on here
and what steps I can take to get C and Java to talk nice in this instance?

How about writing some test code that shows the problem so we can see
what you are really doing and try it ourselves? That said, my best
guess is that there is something wrong with your C string termination.
 
R

Robert M. Gary

In the C code make sure that you either initialize the entire array to
0 (memset) or set the end to null. You may be reading crap off the end
of the buffer. The buffer you pass to atoi MUST have a proper null
terminator. (Alien language to Java guys ;) )

mybuf[n] = '\0';

-Robert
 
M

Matt Humphrey

Jim Bancroft said:
I'm writing out an integer to a socket using java. The client on the
other end is a plane-jane C program, and I'm having trouble figuring out
why the two of them won't talk properly.

I'm writing my integer using a DataOutputStream, like so:

String myString = Integer.toString(myInt);
DataOutputStrea, outp;

//....
outp.writeBytes(myString);

You need to be aware of what encoding is being used for the String as its
Unicode can be translated into bytes in different ways and may not
necessarily be ASCII or whatever your C program expects.
http://mindprod.com/jgloss/encoding.html

Also, how will the reader know how many bytes to read? The bytes you are
writing are not null-terminated and do not have implicit length--TCP is not
packet-oriented. Either set the length to something (like your reader is
doing), send a terminator or send a length-byte first, something like:

//Caution -- Untested code

buffer [] stringBytes = myString.getBytes ("UTF-8");
outp.writeByte (stringBytes.length); // Strings upto 255 chars
outp.writeBytes (stringBytes);
in the C client I'm doing this:

n = read(sockfd,mybuf,sizeof(mybuf));

...where mybuf is an unsigned char[16];

There really aren't any guarantees that the n you receive here is the same
as the number of bytes you write. On any single read you could get fewer or
more characters than you wrote on the corresponding write (depending on the
size of the data and whether there's any more, etc.)

Robert's recommendation is definately true, but you must still consider your
protocol as a whole because you may be reading garbage. Once you've read
the correct amount of data you can put the null terminator into the C
String.

// For reading

n = read (sockfd, mybuf, 1);
int len = (int)mybuf[0];
// len must be <= sizeof(mybuf) // use len to allocate the string area if
you like
// Reading must iterate (not shown here) until the amount read equals the
length
n = read (sockfd, mybuf, len);

// Insert the null terminator yourself
mybuf [len] = '\0';

Matt Humphrey (e-mail address removed) http://www.iviz.com/
 
R

Robert M. Gary

There really aren't any guarantees that the n you receive here is the same
as the number of bytes you write. On any single read you could get fewer or
more characters than you wrote on the corresponding write (depending on the
size of the data and whether there's any more, etc.)


That's true. For some reason I had assumed a web style TCP where he
would close the socket after the single packet, but that's likely not
realistic. Since our core product is UNIX and our newest stuff is Java
(often PC) I often write this type of code. Usually, I'll start all of
my packets with a header. The first byte is a version number (since its
a *&$# to change protocols with a large existing customer base),
followed by a length of the entire packet, and some other header info.
The first read is the header read (reading the exact, fixed size of the
header), the second read is a blocking read for the length of the
packet based on the header.
This works well for connection-oriented TCP because if either side
were to drop off, the other side would know. This would not work with
UDP because its connectionless and the remote could drop off, restart,
and you would not know that you needed to reset and send a new header
(ie. the two could get out of sync).

-Robert
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,754
Messages
2,569,525
Members
44,997
Latest member
mileyka

Latest Threads

Top