Advertisement
If you have a new account but are having problems posting or verifying your account, please email us on hello@boards.ie for help. Thanks :)
Hello all! Please ensure that you are posting a new thread or question in the appropriate forum. The Feedback forum is overwhelmed with questions that are having to be moved elsewhere. If you need help to verify your account contact hello@boards.ie

Java > Networking > Multiplexing Selector

Options
  • 21-02-2003 4:32am
    #1
    Closed Accounts Posts: 358 ✭✭


    lo,

    I'm working on a chat server & client. The server sits waiting for connections from any number of clients, a new Socket is created for each conecting client, and the sockets channel is registered with the Selector object... Everything works fine up untill after I close the socket from the server*. Execution returns from "close( Socket socket )" and makes its way back to the line "numKeys = selector.select()" in "private void getIOEvent()" where an exception is thrown?

    *( closing from client side works fine. Client tells server to close the associated socket and then closes it's own socket ).

    It looks like once the socket and its channel are removed the Selector is pointing to a socket/channel that not there? I've tried a few ways to remove the Selector key without any results, aswell as reading through the API and tryng many other things, but I'm just guessing at this stage.

    Ive included the more relevant code below aswell as the thrown exception, all advice appreciated.

    craig.

    [php]
    // server thread
    public void run() {
    try {
    initNonBlockingServer(); // prepare non-blocking server
    initSelector(); // register server socket chanel with selector

    while( online ) {
    getIOEvent(); // wait for and deal with I/O events
    }
    svrSktChnl.close();
    svrSkt.close();
    selector.close();
    } catch( IOException ie ) {
    ie.printStackTrace();
    }
    }

    // prepare non-blocking server
    private void initNonBlockingServer() {
    try {
    svrSktChnl = ServerSocketChannel.open();
    svrSktChnl.configureBlocking( false );
    svrSkt = svrSktChnl.socket();
    svrSkt.bind( new InetSocketAddress( SERVER_PORT ) );
    } catch( IOException e ) {
    e.printStackTrace();
    }
    }


    // register the server socket chanel with the selector
    private void initSelector() {
    try {
    selector = Selector.open();
    svrSktChnl.register( selector, SelectionKey.OP_ACCEPT );
    readBuffer = ByteBuffer.allocate( BUFFER_SIZE );
    } catch( IOException e ) {
    e.printStackTrace();
    }
    }

    // close socket
    private void close( Socket socket ) {
    // add the socket to the list of sockets to be closed
    closedSockets.add( socket );
    try {
    SocketChannel sc = socket.getChannel();

    // *** test: remove the sktChl's associated Selection key?
    // *** no difference - same exception being thrown in
    // *** private void getIOEvent()"
    // SelectionKey sk = sc.keyFor( selector );
    // sk.cancel();

    sc.close();
    socket.close();
    // tell the gui to behave as the connection is closed
    String id = Integer.toString( socket.getPort() );
    // update the server side gui
    gui.getInternalWindow( id ).setConnected( false );
    gui.setStatusLabel( "Client: " + ( --count ) );

    } catch( IOException e ) {
    e.printStackTrace();
    }
    }

    // wait for an I/O event, deal with it... new connection/incomming chat
    private void getIOEvent() {
    int numKeys = 0;
    try {
    numKeys = selector.select(); // wait for an I/O event
    // *** ERROR: exception thrown
    } catch( IOException e ) {
    e.printStackTrace();
    }
    if( numKeys > 0 ) {
    Set skeys = selector.selectedKeys();
    Iterator it = skeys.iterator();

    while( it.hasNext() ) {
    SelectionKey rsk = ( SelectionKey ) it.next();
    int rskOps = rsk.readyOps();

    // I/O event: new incomming connection, other wise incomming chat
    if( ( rskOps & SelectionKey.OP_ACCEPT ) == SelectionKey.OP_ACCEPT ) {
    // new connection
    getNewConnection( rsk );

    } else if( ( rskOps & SelectionKey.OP_READ ) == SelectionKey.OP_READ ) {
    // incomming chat
    getMessage( rsk );
    }
    }
    removeClosedSockets();
    }
    }

    /* the exception being throw

    java.lang.NullPointerException
    at sun.nio.ch.WindowsSelectorImpl$SubSelector.processFdSet(WindowsSelectorImpl.java:302)
    at sun.nio.ch.WindowsSelectorImpl$SubSelector.processSelectedKeys(WindowsSelectorImpl.java:280)
    at sun.nio.ch.WindowsSelectorImpl$SubSelector.access$2600(WindowsSelectorImpl.java:244)
    at sun.nio.ch.WindowsSelectorImpl.updateSelectedKeys(WindowsSelectorImpl.java:405)
    at sun.nio.ch.WindowsSelectorImpl.doSelect(WindowsSelectorImpl.java:141)
    at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:62)
    at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:67)

    */
    [/php]


Comments

  • Registered Users Posts: 7,468 ✭✭✭Evil Phil


    I can't see where
    [php]
    close( Socket socket )
    [/php]

    is being called from.

    And I have a question, its more for my own general understanding of the Socket class than a suggestion of a bug.

    [php]
    socket.close();
    // tell the gui to behave as the connection is closed
    String id = Integer.toString( socket.getPort() );
    [/php]

    If the Socket is closed would socket.getPort() then be returning 0 as the port has been closed? Probably not as your using the id after this but I was just wondering.


  • Registered Users Posts: 2,010 ✭✭✭Dr_Teeth


    http://www.limewire.org/project/www/nio2.html

    Read section 4.2 and STFW more! :)

    Teeth.


  • Closed Accounts Posts: 358 ✭✭CH


    Thanks for that Teeth,

    I got around it by calling socket.shutDownInput() instead of socket.close() in private void close(Socket socket ). After the selector.select() moves from blocking, the next read from the socket returned EOF and I could now call socket.close() and cancel the SelectionKey associated with it.


Advertisement