SocketChannel.read() блокирует бесконечно

Я с трудом разбираюсь в этом. У меня есть следующий код:

    if (selector.select(1000) <= 0) {
        return;
    }
    Set<SelectionKey> selectionKeys = selector.selectedKeys();
    for (SelectionKey key : selectionKeys) {
        try { 
            SocketEventHandler handler = (SocketEventHandler) key.attachment();
            if (key.isValid() && key.isAcceptable()) {
                handler.becomesAcceptable(key);
            }
            if (key.isValid() && key.isReadable()) {
                handler.becomesReadable(key);
            }

            if (key.isValid() && key.isWritable()) {
                handler.becomesWritable(key);
            }

            if (key.isValid() && key.isConnectable()) {
                handler.becomesConnectable(key);
            }
        } catch (IOException e) {
            key.cancel();
        }
    }
    selector.selectedKeys().clear();

Со следующим кодом обработчика для чтения:

synchronized public void becomesReadable(SelectionKey key) throws IOException {
    ByteBuffer temporaryBuffer = ByteBuffer.allocate(DEFAULT_BYTE_BUFFER_SIZE);
    temporaryBuffer.position(0);
    int read = -1;
    try {
        read = channel.read(temporaryBuffer);
    } catch (IOException e) {
        prefixLogger.debug("Trace:", e);
        close();
    }
    ...
}

И это единственная точка, где вызывается функция-обработчик. Поэтому, если я когда-нибудь попаду в функцию becomeReadable(), канал будет в состоянии для чтения, но вызов read() заблокируется без возврата. Я что-то пропустил?


person cdecker    schedule 06.10.2011    source источник


Ответы (2)


Мне интересно, почему этот метод getsReadable() синхронизируется. Чем меньше синхронизаций при использовании NIO, тем лучше.

Мне также интересно, почему вы не регистрируете IOException и почему вы просто отменяете ключ вместо закрытия канала. Поэтому мне также интересно, какие исключения ввода-вывода вы получаете, о которых вы не знаете.

Кроме того, выделение буферов довольно дорого: вы не должны делать это при каждом чтении, вы должны иметь одно состояние сеанса в экземпляре SocketEventHandler, выделенном для канала.

person user207421    schedule 06.10.2011

Вы вызывали channel.configureBlocking( false ) где-то в своем коде?

Трудно сказать, какой канал вы здесь используете, но я думаю, что SocketChannel изначально создан в режиме блокировки.

person Alexander Pogrebnyak    schedule 06.10.2011
comment
Канал настроен как неблокирующий, и он тоже некоторое время работает в тихом режиме. Проблема появляется через некоторое время. Я проверю состояние socketChannel и обновлю свой исходный пост :-) - person cdecker; 06.10.2011