|
Registering a SocketChannel on Multiple Selectorsby Rajesh Ramchandani(May 2002) We want to hear from you! Please send us your FEEDBACK. The following sample program may contain actual software programs in source code form. This source code is made available for developers to use as needed, pursuant to the terms and conditions of this license.
INTRODUCTION SAMPLE PROGRAM Let's look at our example code. You can download the source here. 1. Import the necessary NIO classes: import java.net.ServerSocket;
2. Review the definitions for two Selectors() (readSelector and writeSelector) which will run in two different threads (readThread and writeThread respectively). A single ServerSocketChannel will be registered to the readSelector and writeSelector. public class SelectorTestServer { /** Single selector for accepts, reads */
/** Single selector for writes */
/** ServerSocketChannel which listens for client connections*/
/** The thread that waits for ready Channels - accept / read*/
/** The thread that waits for ready Channels - write*/
3. Set up the listeners and start listening. protected void startListening () {
//Create the ServerSocketChannel ssch = ServerSocketChannel.open(); //Configure the ServerSocketChannel as Non-Blocking ssch.configureBlocking(false); //Bind the socket to the localhost at port 2000
InetSocketAddress isa = new InetSocketAddress(InetAddress.getLocalHost(),
2000);
//register the ServerSocketChannel with the Selector for accept
ssch.register(readSelector, SelectionKey.OP_ACCEPT);
//Start the Selector threads this.writeThread = new WriteThread();
4. Look at the SelectorThread which will run the Selector() for accepts and reads (OP_ACCEPT and OP_READ). private class SelectorThread extends Thread {
public void run () {
// block until a Channel is ready for I/O
while(readSelector.select() > 0){
// new client connection. Accept the connection.
ServerSocketChannel nextReady = (ServerSocketChannel) sk.channel();
//Register for Reads and writes with the two Selectors
channel.register(readSelector, SelectionKey.OP_READ);
In SelectorThread it is important to call wakeup() on one of the Selectors, else you may not recieve any events on any of the Selectors. According to the specifications of the register() method, "This method may be invoked at any time. If this
method is invoked while another invocation of
5. Look at WriteThread, which will run the Selector() for writes (OP_WRITE). private class WriteThread extends Thread {
public void run () {
6. Provide a method to stop Selector threads. public synchronized void stop () {
7. Write a main() method to show that this works.
public static void main (String args[]){
The server code shown above only prints out "****readable" or "****writable", depending on the state of the client connection. It can be modified to show appropriate actions as required. When you start the server, two threads are started. These threads run readSelector and writeSelector to listen for readable or writable connections to the client. Let's look at the readSelector code to see what happens when the client request comes in. The server waits until a client makes a connection: while(readSelector.select() > 0){
Let's have a Set hold the keys returned from readSelector.selectedKeys(); Set readyKeys = readSelector.selectedKeys();
Use the Iterator to check if there is a new client connection or if this is a current client available for read. If we have a new client connection, sk.isAcceptable() will return true. In that case, we accept the connection and set up the channel for Non-blocking IO:
if (sk.isAcceptable()){
Now let's register the channel with read and write selectors:
channel.register(readSelector, SelectionKey.OP_READ);
Note that we have to call wakeup() on the writeSelector thread, else no write events will be detected by the selector. If the client is not a new client, then check if it is still ready for reads. If yes, then we print "****readable":
if (sk.isReadable()){
This sample Server has been tested to work with a telnet client (telnet
localhost 2000).
Thanks to Tarik Tutill of Isocra for his contributions to this article. | |||||||||||||||||||||