javaniosocketchannel

Using two Selectors for NIO


I need a way to use different Selectors for OP_READ & OP_ACCEPT. I am running into an issue where port scrapers among other entities connecting will delay the handshake and cause latency for anyone registered on OP_READ. My solution was to handle OP_READ & OP_ACCEPT on separate threads but I have been having issues. I first register my acceptor (a selector) to my sever socket channel here...

ssc.register(acceptor, SelectionKey.OP_ACCEPT);

after I accept a client, I register its socket channel to a different selector than it was accepted on:

        SocketChannel sc = ((ServerSocketChannel) key.channel()).accept();
        sc.configureBlocking(false);

        SSLEngine e = context.createSSLEngine();
        e.setUseClientMode(false);
        e.beginHandshake();
        ClientHandler c = new ClientHandler(e);
        if (doHandshake(sc, e)) {
            c.setSocketChannel(sc);
            sc.register(selector, SelectionKey.OP_READ, c);
            System.out.println("Registered socket channel to selector");
        } else {
            sc.close();
            System.out.println("Connection closed: handshake failure.");
        }

For some reason, the selector for OP_READ will never return anything even when it should (when a client sends a message). When I use the same selector for OP_READ as OP_ACCEPT, I have no issues regarding the messages being received. Specifically, I am stuck on selector.select();


Solution

  • I figured it out! I hope this helps anyone here. The solution is to do the following:

    1. Cancel the key.
    2. Register the key with the new selector after the handshake.
    3. Call wakeup() on the selector it was just registered to.