Introduction to Nonblocking Sockets



Introduction:

JDK 1.4 provides developers non-blocking I/O on both sockets and files. For Java network programmers, non-blocking I/O is very exciting, because it makes writing scalable, portable socket applications simpler.

Previously, Java programmers would have to deal with multiple socket connections by starting a thread for each connection. Inevitably, they would encounter issues such as operating system limits, deadlocks, or thread safety violations. Now, the developer can use selectors to manage multiple simultaneous socket connections on a single thread.

java.nio.Buffer class:

Before we are going to learn the non-blocking sockets and face the issues that are hard to resolve, we have to spend some time on java.nio.Buffer class and its implementation classes.

A Buffer instance is merely a limited container of primitive data. It is limited because it can contain a limited number of bytes; in other words, it is not a container, like a Vector or an ArrayList, which theoretically have no limit. In addition, a Buffer instance can only contain items belonging to a Java base type, such as int, char, double, boolean, and so on.

The java.nio.Buffer is an abstract class and having seven implementations, one for each base data type: ByteBuffer, CharBuffer, DoubleBuffer, FloatBuffer, IntBuffer, LongBuffer, and ShortBuffer.

In nonblocking sockets programming, and in general in all contexts where the new I/O system works, it’s very important to figure out how Buffer objects work. This is because the new socket channels use Buffer objects to transfer data across the network.

You can create a new Buffer instance by using one of its static methods:

Buffer.allocate(int capacity) : Allocates a new Byte buffer.
The new buffer’s position will be zero, its limit will be its capacity, and its mark will be undefined. It will have a backing array, and its array offset will be zero.

Buffer.allocateDirect(int capacity) : Allocate a new Direct byte buffer.
The new buffer’s position will be zero, its limit will be its capacity, and its mark will be undefined. Whether or not it has a backing array is unspecified.

Buffer.wrap(byte[] bytes) : Wraps a byte array into a buffer.
The new buffer will be backed by the the given byte array; that is, modifications to the buffer will cause the array to be modified and vice versa. The new buffer’s capacity and limit will be array.length, its position will be zero, and its mark will be undefined. Its backing array will be the given array, and its array offset will be zero.

Buffer.wrap(byte[] bytes, int offset, int length) : Wraps a byte array into a buffer.
The new buffer will be backed by the the given byte array; that is, modifications to the buffer will cause the array to be modified and vice versa. The new buffer’s capacity will be array.length, its position will be offset, its limit will be offset + length, and its mark will be undefined. Its backing array will be the given array, and its array offset will be zero.

Working with Buffer objects is more or less the same as working with streams. The “current position” concept is an important thing to figure out if you want to deal with the Buffer objects properly. At any time, a buffer has a current position indicating an item. Automatically, after each read or write operation, the current position indicates the next item in the buffer.

To write something to the buffer, you can use the put method:

// Writing on a buffer

IntBuffer buffer = IntBuffer.allocate(10);
for (int i=0; i < buffer.capacity(); i++) {
buffer.put(i);
}

The code fragment creates a buffer that can contain 10 integer values. Then, the numbers from 0 to 9 are put in the buffer. As you can see, I use the capacity method to get the capacity of the buffer.

To read the contents of a buffer, you can proceed in the following way:

// Reading from a buffer

buffer.position(0);
while (buffer.hasRemaining()) {
int i = buffer.get();
System.out.println(“i=”+i);
}

Invoking the position method, you can set the current position to 0; that is, at the beginning of the buffer. The hasRemaining method returns true, whether or not there are still elements between the current position and the limit of the buffer. The code inside of the while instruction reads the items by calling the get method and shows them on the console.

It is very important to understand the difference between the limit and the capacity of the buffer. The capacity is the maximum number of items the buffer can contain; the limit is a value, somewhere between 0 and the capacity, representing an arbitrary limitation for the buffer set by using the limit or the flip methods. Take a look at the following example:

// Sample of using flip

buffer.position(5);
buffer.flip();
while (buffer.hasRemaining()) {
int i = buffer.get();
System.out.println(“i=”+i);
}

The current position is set to 5 by the position method. The flip method works like this: it sets the limit to the current position, which is 5; then, it sets the current position again to 0. Therefore, the while loop will scan only the first five elements, because the flip method has set the new limit to 5. Therefore, the shown numbers will be 0, 1, 2, 3, and 4.

Another important method of the Buffer class is clear. It sets the current position to 0 and the limit to the capacity of the buffer. Basically, the clear method annuls the effects provided by previous flip (or limit) invocations. Consider this example:

// Sample of using clear

buffer.clear();
while (buffer.hasRemaining()) {
int i = buffer.get();
System.out.println(“i=”+i);
}

The code above will show the numbers from 0 to 9, independently of the current position and the limit of the buffer.

1 comment

1 ping

  1. Excellent goods from you, man. I’ve understand your stuff previous to and you are just too excellent. I really like what you have acquired here, certainly like what you are stating and the way in which you say it. You make it enjoyable and you still care for to keep it smart. I can not wait to read far more from you. This is really a terrific web site.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: