#java #nio #completionhandler #socketchannel
Вопрос:
Я пытаюсь настроить асинхронный серверный канал, который принимает подключения от клиентов и отправляет и получает сообщения по мере необходимости (не обязательно запрос->ответ). Чтобы облегчить это, я использую асинхронные вызовы чтения и записи с отдельными обработчиками завершения. Проблема, с которой я сейчас сталкиваюсь, заключается в том, что при отключении клиента результат, передаваемый моему обработчику завершения, не равен -1, и протектор продолжает пытаться прочитать. Я хотел бы, чтобы мои соединения с серверами автоматически закрывались при закрытии соответствующего клиентского соединения.
Вот код для моего обработчика завершения чтения:
class ReadHandler implements CompletionHandler<Integer, Attachment> {
@Override
public void completed(Integer result, Attachment att) {
if (result < 0) {
try {
System.out.println("Peer at " att.clientAddr " has disconnected.");
att.channel.close();
} catch (IOException e) {
e.printStackTrace();
}
} else {
att.readBuffer.flip();
int limits = att.readBuffer.limit();
byte bytes[] = new byte[limits];
att.readBuffer.get(bytes, 0, limits);
att.readBuffer.clear();
if(att.hsDone) {
// process incoming msg
peer.processMessage(att.connectedPeerId, bytes);
} else { // if handshake has not been done
att.connectedPeerId = peer.processHandshake(bytes);
System.out.println("Shook hands with peer " att.connectedPeerId ".");
if(att.connectedPeerId < 0) {
try {
att.channel.close();
} catch (IOException e) {
e.printStackTrace();
}
} else {
att.hsDone = true;
att.writeBuffer.put(message.handshakeMsg(peer.id));
att.writeBuffer.flip();
WriteHandler handler = new WriteHandler();
att.channel.write(att.writeBuffer, att, handler);
}
}
att.readBuffer.flip();
att.channel.read(att.readBuffer, att, this);
}
}
@Override
public void failed(Throwable exc, Attachment att) {
System.err.println(exc.getMessage());
}
}
И для моего обработчика завершения записи:
class WriteHandler implements CompletionHandler<Integer, Attachment> {
@Override
public void completed(Integer result, Attachment att) {
att.writeBuffer.clear();
// check if msg needs to be sent
byte data[] = peer.getNextMsg(att.connectedPeerId);
att.writeBuffer.put(data);
att.writeBuffer.flip();
if(att.channel.isOpen())
att.channel.write(att.writeBuffer, att, this);
}
@Override
public void failed(Throwable exc, Attachment att) {
System.err.println(exc.getMessage());
}
}
Мы будем признательны за любую помощь в решении этой проблемы.
Комментарии:
1. Какой результат передается вашему обработчику завершения?
2. @user207421 Результат равен 0 при каждом чтении.
3.Это означает, что буфер чтения уже был заполнен. Вы не
flip()
должны этого делать раньшеread()
(илиput()
). Только доwrite()
илиget()
. Кроме того, вы должны позвонитьcompact()
после тогоget()
и тогоwrite()
, а неclear()
. Вы также должныlimit()-position()
извлечь из него байты, а неlimit()
.4. Спасибо. К сожалению, мое понимание того, как работают буферы и каналы nio, все еще ограничено. Это решило проблему (удаление флипа())