Search code examples
javanio

why does select method return 0 immediately when I try to telnet it?


I am not familiar with Java Nio. I tried to write a little demo like this:

    ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
    serverSocketChannel.bind(new InetSocketAddress(9999)).configureBlocking(false);
    serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

    for (; ; ) {
        int select = selector.select(2_000);
        if (select == 0) {
            System.out.println("no event");
            continue;
        }
        System.out.println("select = " + select);
   }

Timeout is set to 2 seconds and the program print "no event" every 2 seconds.

But when I tried to telnet it and it begins to print "no event" very fast.It seems that the select method returns value 0 without being blocked.

Why? That is the first question.

And when I tried to add some logics in for loop like this:

for (; ; ) {
            int select = selector.select();
            if (select == 0) {
                System.out.println("no event");
                continue;
            }
            System.out.println("select = " + select);
            Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
            System.out.println("iterator = " + iterator.hasNext());
            while (iterator.hasNext()) {
                SelectionKey key = iterator.next();
                iterator.remove();
            }
        }

Then I telnet it again ,the select method returns 1.

Why? That is the second question.

First time ask questions here. Please forgive my poor English.


Solution

  • The number you are providing in select(long) is not the same as Thread.sleep(long). According to:

    https://docs.oracle.com/javase/7/docs/api/java/nio/channels/Selector.html#select(long)

    select is a blocking operation, but it proceeds as soon as it is able to select a channel. So, when you are connected, it will continually loop and output. The long value you are providing is to tell the select(long) method when to give up trying to select a channel, not sleep the thread regardless. In order to guarantee a sleep of a minimum 2 seconds, you need to add Thread.sleep(2000) before the end of the loop.

    As for the return value, select() returns the number of keys that were updated, which may be zero. When you connect again with telnet, you are providing a new key that can be updated. If you have only one connection, there is no need to be selecting a new channel to listen on. Thus, nothing gets toggled. If you have two connections, it makes sense that one of them would be modified each time.