SocketChannel.read () блокируется на неопределенный срок - PullRequest
1 голос
/ 06 октября 2011

Мне трудно понять это. У меня есть следующий код:

    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() блоков не вернется. Я что-то пропустил?

Ответы [ 2 ]

1 голос
/ 07 октября 2011

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

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

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

0 голосов
/ 06 октября 2011

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

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

...