Search code examples
javaselectornio

java nio selector & channel usage problem


i am really puzzled with java nio,

package org.eclipse.java.nio.selector.test;

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.SocketChannel;
import java.util.Iterator;
import java.util.Set;

public class MySelector {
    public static void main(String[] args) throws IOException {
        // Create selector
        Selector selector = null;
        selector = Selector.open();
        ////////////////////////////////////////////////////////////////////////
        SocketChannel socketChannel = SocketChannel.open(new InetSocketAddress(
                "localhost", 4321));
        socketChannel.configureBlocking(false);
        socketChannel.register(selector, SelectionKey.OP_READ);
        /*
         * Let's begin select
         */
        while (true) {
            int readyChannels = selector.select();
            if (readyChannels == 0) continue;

            System.out.println("Hello, selector!");
            Set readyKeys = selector.selectedKeys();
            Iterator it = readyKeys.iterator();  
            while (it.hasNext()) {
                SelectionKey key = (SelectionKey )it.next();
                if (key.isReadable()) {
                    System.out.println("It's readable!");
                }
                it.remove();
            }
        }
    }
}

I want the selector to wait next input event from remote server, but it was fallen into a infinitely loop after the server reply any words, why? i really can not understand, the 'remove' does not work? I do not want to cancel or close the channel, i want to keep the connection, make the client wait for server's reply...


Solution

  • It is necessary to execute reading in the block of isReadable judge. If you do not execute reading the data transmitted from the readable channel, the channel is selected again. So the while loop doesn't stop.

    while (it.hasNext()) {
        SelectionKey key = (SelectionKey )it.next();
        if (key.isReadable()) {
            System.out.println("It's readable!");
    
            // Added read operation
            ByteBuffer buffer = ByteBuffer.allocate(1024);
            Charset charset = Charset.forName("UTF-8");
            buffer.clear();
            if (socketChannel.read(buffer) < 0) {
                // Client connection refused
                socketChannel.close();
                return;
            }
            buffer.flip();
            System.out.println("Value = " + charset.decode(buffer).toString());
    
        }
        it.remove();
    }
    

    I think that the "remove" works. "Hello, Read selector!" might be repeatedly output.