title: Java NIO client
body: <pre><code>import java.io.IOException;
  import java.net.InetAddress;
  import java.net.InetSocketAddress;
  import java.net.Socket;
  import java.net.SocketAddress;
  import java.nio.ByteBuffer;
  import java.nio.channels.SelectionKey;
  import java.nio.channels.Selector;
  import java.nio.channels.ServerSocketChannel;
  import java.nio.channels.SocketChannel;
  import java.util.*;
  
  public class EchoServer {
      private InetAddress addr;
      private int port;
      private Selector selector;
      private Map&lt;SocketChannel,List&lt;byte[]&gt;&gt; dataMap;
  
      public EchoServer(InetAddress addr, int port) throws IOException {
          this.addr = addr;
          this.port = port;
          dataMap = new HashMap&lt;SocketChannel,List&lt;byte[]&gt;&gt;();
          startServer();
      }
  
      private void startServer() throws IOException {
          // create selector and channel
          this.selector = Selector.open();
          ServerSocketChannel serverChannel = ServerSocketChannel.open();
          serverChannel.configureBlocking(false);
  
          // bind to port
          InetSocketAddress listenAddr = new InetSocketAddress(this.addr, this.port);
          serverChannel.socket().bind(listenAddr);
          serverChannel.register(this.selector, SelectionKey.OP_ACCEPT);
  
          log("Echo server ready. Ctrl-C to stop.");
  
          // processing
          while (true) {
              // wait for events
              this.selector.select();
  
              // wakeup to work on selected keys
              Iterator keys = this.selector.selectedKeys().iterator();
              while (keys.hasNext()) {
                  SelectionKey key = (SelectionKey) keys.next();
  
                  // this is necessary to prevent the same key from coming up 
                  // again the next time around.
                  keys.remove();
  
                  if (! key.isValid()) {
                      continue;
                  }
  
                  if (key.isAcceptable()) {
                      this.accept(key);
                  }
                  else if (key.isReadable()) {
                      this.read(key);
                  }
                  else if (key.isWritable()) {
                      this.write(key);
                  }
                  else if (key.isConnectable()) {
                      this.doConnect(key);
                  }
              }
          }
      }
      private void doConnect(SelectionKey key) {
              SocketChannel channel = (SocketChannel) key.channel();
              if (channel.finishConnect()) {
                      /* success */
                      System.out.println("Connected");
              } else {
                      /* failure */
                      System.out.println("failure");
              }
      }
      public void connect(String hostname, int port) throws IOException {
          SocketChannel clientChannel = SocketChannel.open();
          clientChannel.configureBlocking(false);
          clientChannel.connect(new InetSocketAddress(hostname,port));
          clientChannel.register(selector,SelectionKey.OP_CONNECT);
          clientChannel.write(ByteBuffer.wrap(("$Hello "+UserInfo[0]+"|").getBytes("US-ASCII")));
      }
      private void accept(SelectionKey key) throws IOException {
          ServerSocketChannel serverChannel = (ServerSocketChannel) key.channel();
          SocketChannel channel = serverChannel.accept();
          channel.configureBlocking(false);
  
          // write welcome message
          channel.write(ByteBuffer.wrap("Welcome, this is the echo server\r\n".getBytes("US-ASCII")));
  
          Socket socket = channel.socket();
          SocketAddress remoteAddr = socket.getRemoteSocketAddress();
          log("Connected to: " + remoteAddr);        
          dataMap.put(channel, new ArrayList&lt;byte[]&gt;()); // register channel with selector for further IO
          channel.register(this.selector, SelectionKey.OP_READ);
      }
      private void read(SelectionKey key) throws IOException {
          SocketChannel channel = (SocketChannel) key.channel();
  
          ByteBuffer buffer = ByteBuffer.allocate(8192);
          int numRead = -1;
          try {
              numRead = channel.read(buffer);
          }
          catch (IOException e) {
              e.printStackTrace();
          }
          if (numRead == -1) {
              this.dataMap.remove(channel);
              Socket socket = channel.socket();
              SocketAddress remoteAddr = socket.getRemoteSocketAddress();
              log("Connection closed by client: " + remoteAddr);
              channel.close();
              key.cancel();
              return;
          }
          byte[] data = new byte[numRead];
          System.arraycopy(buffer.array(), 0, data, 0, numRead);
          log("Got: " + new String(data, "US-ASCII"));        
          doEcho(key, data); // write back to client
      }
      private void write(SelectionKey key) throws IOException {
          SocketChannel channel = (SocketChannel) key.channel();
          List&lt;byte[]&gt; pendingData = this.dataMap.get(channel);
          Iterator&lt;byte[]&gt; items = pendingData.iterator();
          while (items.hasNext()) {
              byte[] item = items.next();
              items.remove();
              channel.write(ByteBuffer.wrap(item));
          }
          key.interestOps(SelectionKey.OP_READ);
      }
      private void doEcho(SelectionKey key, byte[] data) {
          SocketChannel channel = (SocketChannel) key.channel();
          List&lt;byte[]&gt; pendingData = this.dataMap.get(channel);
          pendingData.add(data);
          key.interestOps(SelectionKey.OP_WRITE);
      }
      private static void log(String s) {
          System.out.println(s);
      }
      public static void main(String[] args) throws Exception {
          new EchoServer(null, 8989);
      }
  }
  </code></pre>
  
  <p>The program works with incoming connections. But when I make an outgoing connection, the program does not work. I need to make some connections in a row through the connect (String hostname, int port) and receive data in a method read(). The program stops working on the line clientChannel.register(...)</p>