I am communicating with a server, each message sent to the server has to be padded with the length of the message,
unsigned int len = htonl(msg.size());
In C running the length through htonl
and padding the message works, in Java AFAIK byte order is already in network order so I assumed all I have to do is write the string length before the message to the stream, but this does not work am I missing something?
stream.write(msg.length());
stream.write(msg.getBytes());
Stream is an OutputStream
.
int htonl(int value) {
return ByteBuffer.allocate(4).putInt(value)
.order(ByteOrder.nativeOrder()).getInt(0);
}
Alternatively
int htonl(int value) {
if (ByteOrder.nativeOrder().equals(ByteOrder.BIG_ENDIAN) {
return value;
}
return Integer.reverseBytes(value);
}
Problem with your implementation is, that the write-method writes only one byte, see the documentation. The important sentence here is: 'The 24 high-order bits of b are ignored.' So stream.write(msg.length());
probably doesn't do what is intended. (I assume msg.length() returns an int, correct me if I'm wrong here.)
Try to write the four bytes of an int:
stream.write(msg.length() % 256);
stream.write((msg.length() / 256) % 256);
stream.write((msg.length() / (256 * 256)) % 256);
stream.write((msg.length() / (256 * 256 * 256)) % 256);
That writes the least significant byte first, you can change the order if wished. You can do the converting to bytes also with bit-shifting, division looks more understandable for me, but that is a question of personal taste.
Take a look at the method Int.reverseBytes(), which on platforms such as x86 will get jitted to the x86's bswapl opcode.
You could condition this off the result of System.getProperty("sun.cpu.endian")
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With