Результат AsynchronousSocketChannel не возвращает -1 в конце потока

#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, все еще ограничено. Это решило проблему (удаление флипа())