FileDocCategorySizeDatePackage
SelectSockets.javaAPI DocExample5125Mon May 20 00:24:28 BST 2002com.ronsoft.books.nio.channels

SelectSockets

public class SelectSockets extends Object
Simple echo-back server which listens for incoming stream connections and echoes back whatever it reads. A single Selector object is used to listen to the server socket (to accept new connections) and all the active socket channels.
author
Ron Hitchens (ron@ronsoft.com)
version
$Id: SelectSockets.java,v 1.5 2002/05/20 07:24:29 ron Exp $

Fields Summary
public static int
PORT_NUMBER
private ByteBuffer
buffer
Constructors Summary
Methods Summary
public voidgo(java.lang.String[] argv)

		int port = PORT_NUMBER;

		if (argv.length > 0) {	// override default listen port
			port = Integer.parseInt (argv [0]);
		}

		System.out.println ("Listening on port " + port);

		// allocate an unbound server socket channel
		ServerSocketChannel serverChannel = ServerSocketChannel.open();
		// Get the associated ServerSocket to bind it with
		ServerSocket serverSocket = serverChannel.socket();
		// create a new Selector for use below
		Selector selector = Selector.open();

		// set the port the server channel will listen to
		serverSocket.bind (new InetSocketAddress (port));

		// set non-blocking mode for the listening socket
		serverChannel.configureBlocking (false);

		// register the ServerSocketChannel with the Selector
		serverChannel.register (selector, SelectionKey.OP_ACCEPT);

		while (true) {
			// this may block for a long time, upon return the
			// selected set contains keys of the ready channels
			int n = selector.select();

			if (n == 0) {
				continue;	// nothing to do
			}

			// get an iterator over the set of selected keys
			Iterator it = selector.selectedKeys().iterator();

			// look at each key in the selected set
			while (it.hasNext()) {
				SelectionKey key = (SelectionKey) it.next();

				// Is a new connection coming in?
				if (key.isAcceptable()) {
					ServerSocketChannel server =
						(ServerSocketChannel) key.channel();
					SocketChannel channel = server.accept();

					registerChannel (selector, channel,
						SelectionKey.OP_READ);

					sayHello (channel);
				}

				// is there data to read on this channel?
				if (key.isReadable()) {
					readDataFromSocket (key);
				}

				// remove key from selected set, it's been handled
				it.remove();
			}
		}
	
public static voidmain(java.lang.String[] argv)


	      
		 
	
		new SelectSockets().go (argv);
	
protected voidreadDataFromSocket(java.nio.channels.SelectionKey key)
Sample data handler method for a channel with data ready to read.

param
key A SelectionKey object associated with a channel determined by the selector to be ready for reading. If the channel returns an EOF condition, it is closed here, which automatically invalidates the associated key. The selector will then de-register the channel on the next select call.


	                                                                 	 
	    
		 
	
		SocketChannel socketChannel = (SocketChannel) key.channel();
		int count;

		buffer.clear();			// make buffer empty

		// loop while data available, channel is non-blocking
		while ((count = socketChannel.read (buffer)) > 0) {
			buffer.flip();		// make buffer readable

			// send the data, don't assume it goes all at once
			while (buffer.hasRemaining()) {
				socketChannel.write (buffer);
			}
			// WARNING: the above loop is evil.  Because
			// it's writing back to the same non-blocking
			// channel it read the data from, this code can
			// potentially spin in a busy loop.  In real life
			// you'd do something more useful than this.

			buffer.clear();		// make buffer empty
		}

		if (count < 0) {
			// close channel on EOF, invalidates the key
			socketChannel.close();
		}
	
protected voidregisterChannel(java.nio.channels.Selector selector, java.nio.channels.SelectableChannel channel, int ops)
Register the given channel with the given selector for the given operations of interest

		if (channel == null) {
			return;		// could happen
		}

		// set the new channel non-blocking
		channel.configureBlocking (false);

		// register it with the selector
		channel.register (selector, ops);
	
private voidsayHello(java.nio.channels.SocketChannel channel)
Spew a greeting to the incoming client connection.

param
channel The newly connected SocketChannel to say hello to.

		buffer.clear();
		buffer.put ("Hi there!\r\n".getBytes());
		buffer.flip();

		channel.write (buffer);