O
Owen Jacobson
Salve.
I'm working on an event-driven network system based on an NIO selector
(for determining when an event has "fired"). The basic process is to
register a SelectableChannel and a handler for that channel, which
registers the channel with the underlying Selector (obtaining a
SelectionKey). I then loop, calling selector.select () and iterating over
the selector.selectedKeys () set and dispatching events as indicated by
the isAcceptable(), isConnectable(), isReadable(), and isWritable()
methods on each key.
Obviously, each channel must be placed in non-blocking mode before
registering it with the Selector.
I've run into a bit of an interesting behaviour on the part of the
Selector, though: once an event fires, it never "unfires". If socket A is
a ServerSocketChannel and is interested in OP_ACCEPT, when a connection
comes in the key for A is marked isAcceptable() and an appropriate event
is dispatched, which results in the handler calling A.accept () and
registering the resulting socket (B).
The problem arises when data arrives on B: selector.select() returns, as
expected, but the key for A is still marked isAcceptable (), even though
no new connection has been recieved for A -- only data on B. This works
the other way around, too: if a new connection arrives, select() returns,
and the key for B is marked isReadable() if any data has ever arrived on
that socket, even if none is present right now.
While these two situations are easy to detect (accept returns null, read
returns 0), it seems awfully wasteful to call accept/read/write on every
socket. What have I missed?
Owen
I'm working on an event-driven network system based on an NIO selector
(for determining when an event has "fired"). The basic process is to
register a SelectableChannel and a handler for that channel, which
registers the channel with the underlying Selector (obtaining a
SelectionKey). I then loop, calling selector.select () and iterating over
the selector.selectedKeys () set and dispatching events as indicated by
the isAcceptable(), isConnectable(), isReadable(), and isWritable()
methods on each key.
Obviously, each channel must be placed in non-blocking mode before
registering it with the Selector.
I've run into a bit of an interesting behaviour on the part of the
Selector, though: once an event fires, it never "unfires". If socket A is
a ServerSocketChannel and is interested in OP_ACCEPT, when a connection
comes in the key for A is marked isAcceptable() and an appropriate event
is dispatched, which results in the handler calling A.accept () and
registering the resulting socket (B).
The problem arises when data arrives on B: selector.select() returns, as
expected, but the key for A is still marked isAcceptable (), even though
no new connection has been recieved for A -- only data on B. This works
the other way around, too: if a new connection arrives, select() returns,
and the key for B is marked isReadable() if any data has ever arrived on
that socket, even if none is present right now.
While these two situations are easy to detect (accept returns null, read
returns 0), it seems awfully wasteful to call accept/read/write on every
socket. What have I missed?
Owen