Pergunta

Ao escrever um código de teste eu descobri que Selector.select () pode retornar sem Selector.selectedKeys () contendo todas as chaves para processo. Isto acontece num ciclo apertado quando registar um aceitar () ed canal com

SelectionKey.OP_READ | SelectionKey.OP_CONNECT

como as operações de interesse.

De acordo com os documentos, seleccione () deve retornar quando:

1) Existem canais que podem ser postas em prática.

2) Você chama explicitamente Selector.wakeup (.) - sem chaves são selecionados

3) Você explicitamente Thread.interrupt () o fio fazer o select () -. Nenhuma tecla for selecionado

Se eu ficar sem chaves após o select () Eu devo ser em casos (2) e (3). No entanto, o meu código não está chamando de despertar () ou interrupção () para iniciar esses retornos.

Todas as ideias sobre o que está causando esse comportamento?

Foi útil?

Solução

Resposta curta:. OP_CONNECT remover da lista de operações que você está interessado para a conexão aceita - uma conexão aceita já está conectado

Eu consegui reproduzir o problema, que pode ser exatamente o que está acontecendo com você:

import java.net.*;
import java.nio.channels.*;


public class MyNioServer {
  public static void main(String[] params) throws Exception {
    final ServerSocketChannel serverChannel = ServerSocketChannel.open();
    serverChannel.configureBlocking(true);
    serverChannel.socket().bind(new InetSocketAddress("localhost", 12345));
    System.out.println("Listening for incoming connections");
    final SocketChannel clientChannel = serverChannel.accept();
    System.out.println("Accepted connection: " + clientChannel);


    final Selector selector = Selector.open();
    clientChannel.configureBlocking(false);
    final SelectionKey clientKey = clientChannel.register(selector, SelectionKey.OP_READ | SelectionKey.OP_CONNECT);
    System.out.println("Selecting...");
    System.out.println(selector.select());
    System.out.println(selector.selectedKeys().size());
    System.out.println(clientKey.readyOps());
  }
}

Depois que o servidor acima recebe uma ligação, o primeiro select() nas saídas de conexão sem bloqueio e não há chaves com operações prontas. Eu não sei por que se comporta em Java desta maneira, mas parece que muitas pessoas mordido por este comportamento.

O resultado é o mesmo em Sun JVM 1.5.0_06 no Windows XP, bem como da Sun JVM 1.5.0_05 e 1.4.2_04 no Linux 2.6.

Outras dicas

A razão é que OP_CONNECT e OP_WRITE são a mesma coisa sob o capô, então você nunca deve ser registrado para ambos simultaneamente (OP_ACCEPT ditto e OP_READ), e você nunca deve ser registrado para OP_CONNECT em tudo quando o canal já está conectado , como é neste caso, depois de ter sido aceite.

E OP_WRITE é quase sempre pronto, exceto quando o buffer de envio tomada em e kernel é completo, assim você só deve se registrar para que depois que você começa uma gravação comprimento zero. Então por registrar o canal já conectado para OP_CONNECT, você estava realmente registrar para OP_WRITE, que estava pronto, por isso select() foi acionado.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top