Misc NIO questions

I need som help with my run() method. How should I accept and register the connections from the clients? I want to both read from the and write to them. How can I detect if the client “hang up” on me (now the server crashes when the client does)?

One more thing, how to unbind a socket if I want to reuse the same port later (i.e. rebooting the server)?

import java.io.IOException;
import java.net.InetSocketAddress;
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.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
import java.util.Iterator;

public class ServerController implements Runnable
{
      // Network fields.
      private static final int DEFAULT_PORT = 1337;
      private ByteBuffer buffer = ByteBuffer.allocateDirect(1024);
      private Charset ascii = Charset.forName("us-ascii");
      private CharsetEncoder asciiEncoder = ascii.newEncoder();
      private Selector selector;
      private ServerSocketChannel ssChannel;

      private void start()
      {
            try
            {
                  selector = Selector.open();
                  
                  ssChannel = ServerSocketChannel.open();
                  ssChannel.configureBlocking(false);
                  ssChannel.socket().bind(new InetSocketAddress(DEFAULT_PORT));
                  ssChannel.register(selector, SelectionKey.OP_ACCEPT);
            }
            catch (IOException e)
            {
                  e.printStackTrace();
            }
      }

      public void run()
      {
            while (running)
            {
                  try
                  {
                        selector.select();
                        
                        Iterator it = selector.selectedKeys().iterator();
                        while (it.hasNext())
                        {
                              SelectionKey sk = (SelectionKey) it.next();
                              it.remove();
                              
                              if (sk.isAcceptable())
                              {
                                    ServerSocketChannel acceptChannel = (ServerSocketChannel) sk.channel();
                                    SocketChannel sChannel = acceptChannel.accept();
                                    sChannel.register(selector, SelectionKey.OP_READ);
                              }
                              else if (sk.isReadable())
                              {
                                    SocketChannel sChannel = (SocketChannel) sk.channel();
                                    if (sChannel.read(buffer) == -1)
                                    {
                                          sk.cancel();
                                    }
                              }
                        }
                        
                        Thread.sleep(1000);
                  }
                  catch (InterruptedException e)
                  {
                        System.err.println("Server interrupted during sleep.");
                        System.exit(-1);
                  }
                  catch (IOException ioe)
                  {
                        ioe.printStackTrace();
                  }
            }
      }

      public static void main(String[] args)
      {
            new ServerController();
      }
}

Thanks!

  • Johan

I don’t have the time to check through the code for your first question, sorry. There are many NIO tutorials out there. Get comfy and start pouring over them :slight_smile:

As for the “unbind” – you just close the channel. Also, look into ServerSocketChannel.getSocket().setReuseAddress(). It may be useful in your case.