CharBuffer view on ByteBuffer and No Bytes Written to SocketChannel

Hi,

I've actually got two problems that might be connected. I'm new to the java.nio.* package. I wanted to try SocketChannel's to see if I could improve performance.

If this isn't the appropriate place for java.nio questions, just let me know.

My first problem is that I create a ByteBuffer by allocating x number of bytes. These bytes are the length of the message I want to send to the server. Then, I attempt to get a CharBuffer view of the ByteBuffer (buffer.asCharBuffer). For some reason, it only returns a CharBuffer with half the capacity of the ByteBuffer. So of course, when I stuff my String into the CharBuffer, it doesn't fit.

Well, I hack that and make the ByteBuffer twice as big. Which brings me to problem two, my SocketChannel does not write any bytes to the server when told to.

Here's the code (with hack):

ByteBuffer buf;

CharBuffer cbuf;

SocketChannel sockChan;

try{

int msgLength = message.length();

logger.info("Message length=" + msgLength);

logger.info("message length in bytes=" + message.getBytes().length);

buf = ByteBuffer.allocateDirect(msgLength*2);

logger.info("position=" + buf.position());

logger.info("capacity=" + buf.capacity());

logger.info("limit=" + buf.limit());

cbuf = buf.asCharBuffer();

logger.info("capacity of cbuf=" + cbuf.capacity());

cbuf.put(message);

buf.flip();

sockChan = SocketChannel.open();

sockChan.configureBlocking(true);

sockChan.socket().setSoTimeout(TIMEOUT_MS);

logger.info("socket configured");

sockChan.connect(new InetSocketAddress(ipAddress, portNumber));

int numBytesWritten = sockChan.write(buf);

logger.info("connected and wrote message. NumBytes writen=" + numBytesWritten);

if (numBytesWritten != msgLength){

//throw error

logger.error("The number of bytes written do not match the " +

"message length (in bytes).");

}

}catch (IOException e1){

// TODO Auto-generated catch block

e1.printStackTrace();

}

And the console outputs the following:

[Dec 13, 11:46:17] INFO - Message length=50

[Dec 13, 11:46:17] INFO - message length in bytes=50

[Dec 13, 11:46:17] INFO - position=0

[Dec 13, 11:46:17] INFO - capacity=100

[Dec 13, 11:46:17] INFO - limit=100

[Dec 13, 11:46:17] INFO - capacity of cbuf=50

[Dec 13, 11:46:17] INFO - socket configured

[Dec 13, 11:46:17] INFO - connected and wrote message. NumBytes writen=0

[Dec 13, 11:46:17] ERROR - The number of bytes writtendo not match the message length (in bytes).

My batch program freezes at this point. Don't know why it does that either.

Thanks for any help,

CowKing

[3534 byte] By [IamCowKinga] at [2007-11-26 12:30:03]
# 1

> ByteBuffer (buffer.asCharBuffer). For some reason, it

> only returns a CharBuffer with half the capacity of

> the ByteBuffer.

The reason is simply that chars are twice as big as bytes, so you can only get half as many of them into the same space. The capacity of a ByteBuffer is measured in bytes. The capacity of a CharBuffer is measured in chars. The capacity of a DoubleBuffer is measured in doubles.

> Well, I hack that and make the ByteBuffer twice as

> big. Which brings me to problem two, my SocketChannel

> does not write any bytes to the server when told to.

As it says in the Javadoc for ByteBuffer, a view buffer has its own position, limit, and mark. When you put data into it the data goes 'through' into the underlying ByteBuffer but the revised position/limit do not. You have to do that yourself manually, remembering to multiply by two as above to account for the difference widths of chars and bytes.

ejpa at 2007-7-7 15:40:17 > top of Java-index,Archived Forums,Socket Programming...
# 2

Correct on both accounts! =)

Alright, this is a little embarassing and frustrating. A Java char is indeed two bytes long (16-bit unicaode character, not 8 bit ASCII). Even though when you perform a string.getBytes().length it returns the length of the String (not 2 times the length of the String). Which just doesn't make sense and throws stupid people like me off.

CowKing

IamCowKinga at 2007-7-7 15:40:17 > top of Java-index,Archived Forums,Socket Programming...
# 3
It returns the length of the String in chars. Quite consistent with the above.
ejpa at 2007-7-7 15:40:17 > top of Java-index,Archived Forums,Socket Programming...
# 4

If you have a String with length of 10...

A string is basically a char array. So if 1 char occupies 2 bytes, then the string will be occupying 20 bytes.

However, when you call string.getBytes().length it will be 10 bytes.

The numbers don't add up. This is what threw me off in the first place.

However, the getBytes() method of String states in the API that it will return the platform default character set. That's why those numbers don't add up properly. Unless my platform is set to 16-bit Unicode, Java will not retrieve the bytes via that charset. Instead, my platform is set to ISO-8859-1 (aka, ASCII) which is an 8-bit charset (or 1 byte per char).

It just confused me is all.

Thanks for your help! =)

CowKing

IamCowKinga at 2007-7-7 15:40:17 > top of Java-index,Archived Forums,Socket Programming...
# 5
String.getBytes() turns those 10 16-bit chars into 10 8-bit bytes.I'm not sure what you expected here.
ejpa at 2007-7-7 15:40:17 > top of Java-index,Archived Forums,Socket Programming...