Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java NIO Server

Tags:

java

nio

Currently I'm working on a Java NIO Server (single-threaded) and have encountered some problems. The server accepts incoming connections, writes initial packets (the packet contains some data that client uses for further communication) to clients but doesn't read from them. The server tries to read only when I close the client and, of course, it returns -1.

When accepting connection, it's being registered under:

selectionKey = socketChannel.register(_selector, SelectionKey.OP_READ)

selectionKey.isReadable() returns false (should it?)

Before sending initial packet, ops are changed to:

_selectionKey.interestOps(_selectionKey.interestOps() | SelectionKey.OP_WRITE)

After sending initial packet, ops are changed to:

selectedKey.interestOps(selectedKey.interestOps() & ~SelectionKey.OP_WRITE)

Packet gets sent.

What could be the problem? Can it be related to client?

like image 507
Testas Avatar asked Aug 13 '11 23:08

Testas


1 Answers

selectionKey.isReadable() returns false (should it?)

Certainly, until there is data to read, or end of stream.

Before sending initial packet, ops are changed to:

_selectionKey.interestOps(_selectionKey.interestOps() | SelectionKey.OP_WRITE)

Bad idea. OP_WRITE is almost always ready, i.e. except when the socket send buffer is full, so you will just cause your Selector.select() method to spin mindlessly.

When you want to write to the channel, just write. Do that in the classic loop:

while (buffer.position() > 0)
{
    buffer.flip();
    int count = channel.write(buffer);
    buffer.compact();
    if (count == 0)
    {
        // see below ...
    }
}

If count is zero, you should then register for OP_WRITE, break out of the loop, and go back to the Selector loop. If you got out of this loop without that happening, deregister OP_WRITE.

Note that this implies you have a write buffer per channel. For similar reasons (read() returning zero) you also need a read buffer per channel. That in turn implies a channel 'session' object that contains them both, and that is probably the attachment of the channel's selection key.

like image 89
user207421 Avatar answered Oct 06 '22 00:10

user207421