Re: Question about non-blocking NIO and Selection Keys
Zachary Turner wrote:
I am new to non-blocking socket i/o so please go easy on my terrible
code below :)
That being said, I have a socket that must be used for reading and
writing, but nothing else. So I initialize my socket early on as:
asyncSelector = new Selector();
sockC.configureBlocking(false);
sockC.register(asyncSelector, SelectionKey.OP_WRITE |
SelectionKey.OP_READ);
Now, whenever I need to write to my socket, I do the following:
public void write(ByteBuffer buf) throws ServerException {
int bytesWritten = 0;
int bytesToWrite = buf.remaining();
while (bytesWritten < bytesToWrite) {
limitBuffer(buf, bytesToWrite, bytesWritten,
MAX_BYTES_PER_BUF_WRITE);
waitForOperation(SelectionKey.OP_WRITE);
int bytesWrittenThisTime = sockC.write(buf);
if (bytesWrittenThisTime == -1)
throw new ServerException("Remote host unexpectedly closed
the connection");
else
bytesWritten += bytesWrittenThisTime;
}
}
public void waitForOperation(int operation) throws ServerException {
while (true) {
try {
if (asyncSelector.select() == 0)
continue;
Set<SelectionKey> selected = asyncSelector.selectedKeys();
for (Iterator<SelectionKey> i = selected.iterator();
i.hasNext(); ) {
if ((i.next().readyOps() & operation) != 0)
return;
}
}
catch (IOException e) {
throw new ServerException("An error occured while performing
a socket operation.");
}
}
}
as such I think it's most likely to be the culprit. Can anyone
provide any observations or suggestions as how to improve this code?
No, but I'm no NIO expert so don't dispair yet. However I do have a
couple of observations.
First, writting a small number of bytes seems counter productive with
NIO. If you are blocking, it make sense to limit the number of bytes
written so you don't block too long. With NIO, this shouldn't be an
issue, so for efficiency (speed) you should just hand NIO as much data
as you have and let it deal with sending it out.
> limitBuffer(buf, bytesToWrite, bytesWritten,
> MAX_BYTES_PER_BUF_WRITE);
The above line makes no sense to me. Why limit the bytes if the
operation won't block?
Second, you say your IO needs to be non-blocking, but you have this
method call with the word "wait" in it right in the middle of your
routine, which seems suspect. If you don't want to block, why wait? It
makes no sense. In particular, this line:
> if (asyncSelector.select() == 0)
will block, so you might be slowing yourself down there. It's worth
looking into, I think.
Good luck.