У меня есть простой неблокирующий сервер с основным циклом:
try {
while (selector.select() > -1) {
// Wait for an event one of the registered channels
// Iterate over the set of keys for which events are available
Iterator selectedKeys = selector.selectedKeys().iterator();
while (selectedKeys.hasNext()) {
SelectionKey key = (SelectionKey) selectedKeys.next();
selectedKeys.remove();
try {
if (!key.isValid()) {
continue;
}
if (key.isConnectable()) {
connect(key);
}
// Check what event is available and deal with it
if (key.isAcceptable()) {
accept(key);
}
if (key.isReadable()) {
read(key);
}
if (key.isWritable()) {
write(key);
}
} catch (Exception e) {
e.printStackTrace();
close(key);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
В разделе чтение/запись проверяю, есть ли что читать/писать, если нет - то пытаюсь закрыть канал:
if (channel.read(attachment.buffer) < 1)
close(key);
Метод закрытия:
private void close(SelectionKey key) throws IOException {
key.cancel();
key.channel().close();
}
Но во время обработки этого кода я получаю исключение в основном цикле (оно перехватывается, но я предположил, что что-то не так), я получаю эту трассировку стека:
java.nio.channels.CancelledKeyException
at sun.nio.ch.SelectionKeyImpl.ensureValid(Unknown Source)
at sun.nio.ch.SelectionKeyImpl.readyOps(Unknown Source)
at java.nio.channels.SelectionKey.isWritable(Unknown Source)
Таким образом, он терпит неудачу в основном цикле, когда входит в раздел записи, закрывает канал и возвращается к основному циклу в «доступном для записи», если раздел и терпит неудачу с таким исключением. Какие-либо предложения?
SocketChannel.read
может вернуть0
и, кстати, не обязательно означает ошибку. - person obataku   schedule 08.08.2012