Jos A. Horsmeier wrote:
> I'm hopping in a bit late, but nevertheless. I've implemented something
> similar and, the lazy bones that I am, I just wrapped a DataInputStream
> and DataOutputStream around the raw SocketStream (this is the Java side
> of the story). Those two streams take care of about anything.
Bingo!
That's probably much of why they are as they are.
> If the other side happens to the 'C side' running on some box, all the
> other side has to do is use the htonl(), ntohl() macros and their compadres
> to send/receive binary integer data. Binary byte arrays can be passed
> around without conversion.
Generally, I dislike those macros. First, 'cause macros are bad.

But more because there are some usage problems. On a little-endian
machine, they flip bytes. If one calls something twice, you undo the fix
and break it again. Also, you have to play magic anyway to get the
initial value.
I prefer clean code that just uses bit math to shift things. No macros
needed, and works on any platform regardless of primitive size. Since
you have to play a little code to get the size issue compensated for,
you can easily fix byte order at the same time.
>
> Strings can be passed around using a little trick -- Java characters take
> up 16 bits (the Unicode stuff) while, normally the C side uses char[]s
> to store their strings. (wide characters are a different cup of tea).
> This is how Java Strings can be written to the socket:
>
> void write(String s) {
> byte[] buf= s.getBytes("ISO-8859-1");
> write(buf);
> }
That's probably not good. Mainly because Latin1 (AKA ISO-8859-1) will
loose lots of characters. On a MS Windows platform you will lose 32
places in the visible character range. On a Mac, you'll use 50%.
It's better to use UTF-8 for your wire format.
> String s= new String(buf, "ISO-8859-1");
Here too.
> Double values are easy to send/receive too; simple reverse the byte
> order on the C side before sending and after receiving and simply
> read/write the double on the Java side.
Not quite.
Do that on my Mac G3 and it will be scrambled.
Seriously, though, this is a little tricky. So I think it's a good idea
to add some asserts in the C code.
Assert that sizeof(float) == 32 and that sizeof(double) == 64. Then you
might want to add a simple one to be sure that your platform uses
IEE754. If any of these are not true, then you'll need some platform
specific C code in that case (of course, since IEEE754 became standard
and widespread, that's much easier)
And you want to be sure not to just "reverse" the bytes. Instead you
want to "send them in network byte order". IIRC, this is one of the few
places where I cast a pointer and use htnl.