tags:

views:

521

answers:

2

I want to write java tcp socket programming using java NIO. Its working fine. But I am using the same selector for accepting reading from and writing to the clients.

How Can I create different selectors for accepting new connection in java NIO, reading and writing. Is there any online help.

Actually when I am busy in reading or writing my selector uses more iterator. So If more number of clients are connected then performance of accepting new coneection became slow. But I donot want the accepting clients to be slow

// Create a selector and register two socket channels Selector selector = null; try { // Create the selector selector = Selector.open();

    // Create two non-blocking sockets. This method is implemented in
    // e173 Creating a Non-Blocking Socket.
    SocketChannel sChannel1 = createSocketChannel("hostname.com", 80);
    SocketChannel sChannel2 = createSocketChannel("hostname.com", 80);

    // Register the channel with selector, listening for all events
    sChannel1.register(selector, sChannel1.validOps());
    sChannel2.register(selector, sChannel1.validOps());
} catch (IOException e) {
}

// Wait for events
while (true) {
    try {
        // Wait for an event
        selector.select();
    } catch (IOException e) {
        // Handle error with selector
        break;
    }

    // Get list of selection keys with pending events
    Iterator it = selector.selectedKeys().iterator();

    // Process each key at a time
    while (it.hasNext()) {
        // Get the selection key
        SelectionKey selKey = (SelectionKey)it.next();

        // Remove it from the list to indicate that it is being processed
        it.remove();

        try {
            processSelectionKey(selKey);
        } catch (IOException e) {
            // Handle error with channel and unregister
            selKey.cancel();
        }
    }
}

public void processSelectionKey(SelectionKey selKey) throws IOException {
    // Since the ready operations are cumulative,
    // need to check readiness for each operation
    if (selKey.isValid() && selKey.isConnectable()) {
        // Get channel with connection request
        SocketChannel sChannel = (SocketChannel)selKey.channel();

        boolean success = sChannel.finishConnect();
        if (!success) {
            // An error occurred; handle it

            // Unregister the channel with this selector
            selKey.cancel();
        }
    }
    if (selKey.isValid() && selKey.isReadable()) {
        // Get channel with bytes to read
        SocketChannel sChannel = (SocketChannel)selKey.channel();

        // See e174 Reading from a SocketChannel
    }
    if (selKey.isValid() && selKey.isWritable()) {
        // Get channel that's ready for more bytes
        SocketChannel sChannel = (SocketChannel)selKey.channel();
        }
}

Thanks Deepak

A: 

There is plenty of online help.

If you want to create a new selector, go ahead and create another one (the same way it was done in the sample code you copied). You can register channels with it for just the connect operation if you want (the docs cover this, but the operation is OP_ACCEPT). You probably want a thread pool to handle the work of client processing - that way your main thread can queue up work items and get back onto accepting new connections on the listening socket right away.

JimG
I was unable to create
Well why not paste whatever code you're actually using, instead of sample client code? If you're accepting connections, you must be using a ServerSocketChannel somewhere.
JimG
A: 

Each selector needs its own thread.

If you want multiple selectors, why not just use blocking NIO, that would be a lot simpler. Non-blocking IO only makes sense if you want to connections to share threads.

Peter Lawrey
I don't see anything to suggest two selectors can't be used on the same thread. It seems to work fine for me (though two is also not necessary for just about any reason I can think of).
JimG
You can use any number of selectors in one thread. However, I don't see the point i.e. what does it give you that a single selector wouldn't?
Peter Lawrey
Sounds like we are in agreement. It was just the wording of "needs its own thread" that was confusing me. It would be possible to have one selector exclusively to deal with accept operations, so you could prioritise those over read/write operations. I think this is what he's asking for, even though it doesn't make sense and won't actually improve performance in the way he expects without additional work.
JimG
There are some valid patterns that use multiple selectors at different stages. For instance, one selector to accept connections with another selector for active reads/writes. Sometimes this makes it easier to deal with the "quirks" of SelectionKeys showing up as ready too often (i.e., on multiple calls to select()) because the worker thread hasn't gotten around to clearing the op yet, or the issues of changing interest ops in non-select()-calling threads. Grizzly does this very well.
mtnygard