Java NIO client

I need to make the server is able to hold about 500 connections and operates on a single thread. The server itself should make all the connections. Where can I find examples of finished implementations?


I have an example, but it does not work
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.nio.channels.spi.SelectorProvider;
import java.util.*;
public class NioClient implements Runnable {
     // The host:port combination to connect to
     private InetAddress hostAddress;
     private String host;
     private int port;
     // The selector we'll be monitoring
     private Selector selector;
     // The buffer into which we'll read data when it's available
     private ByteBuffer readBuffer = ByteBuffer.allocate(8192);
     // A list of PendingChange instances
     private List pendingChanges = new LinkedList();
     // Maps a SocketChannel to a list of ByteBuffer instances
     private Map pendingData = new HashMap();
     // Maps a SocketChannel to a RspHandler
     private Map rspHandlers = Collections.synchronizedMap(new HashMap());
     public NioClient() {
          try {this.selector = this.initSelector();} catch(IOException e){}
     public void connect(String host, int port, RspHandler handler) throws IOException {
          this.hostAddress = hostAddress;
 = host;
          this.port = port;
          this.send("$Hello |".getBytes(), handler);
     public void send(byte[] data, RspHandler handler) throws IOException {
          // Start a new connection
          SocketChannel socket = this.initiateConnection();
          // Register the response handler
          this.rspHandlers.put(socket, handler);
          // And queue the data we want written
          synchronized (this.pendingData) {
               List queue = (List) this.pendingData.get(socket);
               if (queue == null) {
                    queue = new ArrayList();
                    this.pendingData.put(socket, queue);
          // Finally, wake up our selecting thread so it can make the required changes
     public void run() {
          while (true) {
               try {
                    // Process any pending changes
                    synchronized (this.pendingChanges) {
                         Iterator changes = this.pendingChanges.iterator();
                         while (changes.hasNext()) {
                              ChangeRequest change = (ChangeRequest);
                              switch (change.type) {
                              case ChangeRequest.CHANGEOPS:
                                   SelectionKey key = change.socket.keyFor(this.selector);
                              case ChangeRequest.REGISTER:
                                   change.socket.register(this.selector, change.ops);
                    // Wait for an event one of the registered channels
                    // Iterate over the set of keys for which events are available
                    Iterator selectedKeys = this.selector.selectedKeys().iterator();
                    while (selectedKeys.hasNext()) {
                         SelectionKey key = (SelectionKey);
                         if (!key.isValid()) {
                         // Check what event is available and deal with it
                         if (key.isConnectable()) {
                         } else if (key.isReadable()) {
                         } else if (key.isWritable()) {
               } catch (Exception e) {
     private void read(SelectionKey key) throws IOException {
          SocketChannel socketChannel = (SocketChannel);
          // Clear out our read buffer so it's ready for new data
          // Attempt to read off the channel
          int numRead;
          try {
               numRead =;
          } catch (IOException e) {
               // The remote forcibly closed the connection, cancel
               // the selection key and close the channel.
          if (numRead == -1) {
               // Remote entity shut the socket down cleanly. Do the
               // same from our end and cancel the channel.
          // Handle the response
          this.handleResponse(socketChannel, this.readBuffer.array(), numRead);
     private void handleResponse(SocketChannel socketChannel, byte[] data, int numRead) throws IOException {
          // Make a correctly sized copy of the data before handing it
          // to the client
          byte[] rspData = new byte[numRead];
          System.arraycopy(data, 0, rspData, 0, numRead);
          // Look up the handler for this channel
          RspHandler handler = (RspHandler) this.rspHandlers.get(socketChannel);
          // And pass the response to it
          if (handler.handleResponse(rspData)) {
               // The handler has seen enough, close the connection
     private void write(SelectionKey key) throws IOException {
          SocketChannel socketChannel = (SocketChannel);
          synchronized (this.pendingData) {
               List queue = (List) this.pendingData.get(socketChannel);
               // Write until there's not more data ...
               while (!queue.isEmpty()) {
                    ByteBuffer buf = (ByteBuffer) queue.get(0);
                    if (buf.remaining() > 0) {
                         // ... or the socket's buffer fills up
               if (queue.isEmpty()) {
                    // We wrote away all data, so we're no longer interested
                    // in writing on this socket. Switch back to waiting for
                    // data.
     private void finishConnection(SelectionKey key) throws IOException {
          SocketChannel socketChannel = (SocketChannel);
          // Finish the connection. If the connection operation failed
          // this will raise an IOException.
          try {
          } catch (IOException e) {
               // Cancel the channel's registration with our selector
          // Register an interest in writing on this channel
     private SocketChannel initiateConnection() throws IOException {
          // Create a non-blocking socket channel
          SocketChannel socketChannel =;
          // Kick off connection establishment
          socketChannel.connect(new InetSocketAddress(, this.port));
          // Queue a channel registration since the caller is not the
          // selecting thread. As part of the registration we'll register
          // an interest in connection events. These are raised when a channel
          // is ready to complete connection establishment.
          synchronized(this.pendingChanges) {
               this.pendingChanges.add(new ChangeRequest(socketChannel, ChangeRequest.REGISTER, SelectionKey.OP_CONNECT));
          return socketChannel;
     private Selector initSelector() throws IOException {
          // Create a new selector
          return SelectorProvider.provider().openSelector();
public class RspHandler {
     private byte[] rsp = null;
     public synchronized boolean handleResponse(byte[] rsp) {
          this.rsp = rsp;
          return true;
     public synchronized void waitForResponse() {
          while(this.rsp == null) {
               try {
               } catch (InterruptedException e) {
          System.out.println(new String(this.rsp));
}          NioClient NioClient = new NioClient();
          Thread t = new Thread(NioClient);
          RspHandler handler = new RspHandler();          
          NioClient.connect("", 27040, handler);
          NioClient.connect("", 27040, handler);
          NioClient.connect("", 27011, handler);
          NioClient.connect("", 27012, handler);
Edited by: 915967 on 01.08.2012 7:07