Java NIO select()반환하지 않고 선택한 키는데,그 이유는 무엇입니까?
문제
에서 작성 테스트 코드는 선택합니다.select()반환 할 수 있습니다 수 없는 선택입니다.selectedKeys()를 포함하는 모든 키는 과정이다.에서 이런 일이 일어나는 루프 등록할 때에는 동의()ed 채널
SelectionKey.OP_READ | SelectionKey.OP_CONNECT
으로 운영합니다.
에 따라 문서를 선택,()반환해야 합니다면:
1)가 있는 채널 행동될 수 있습니다.
2)당신은 당신이 명시적으로 호출기를 선택하세요.wakeup()-키이 선택됩니다.
3)당신은 명시적으로 스레드가 있습니다.인터럽트()스레드하 선택(다)-키이 선택됩니다.
면 아무 키 select()내에 있어야 합니다 경우(2)and(3).그러나 나의 코드가 호출하지 wakeup()또는 인터럽트()를 시작하는 이러한 반환합니다.
으로 모든 아이디어이 행동의 원인이 무엇?
해결책
짧은 답변 : 제거하십시오 OP_CONNECT
허용 된 연결에 관심이있는 작업 목록에서 허용 된 연결이 이미 연결되어 있습니다.
나는 문제를 재현 할 수 있었는데, 이것은 당신에게 일어나는 일이 될 수 있습니다.
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());
}
}
위의 서버가 연결을 수신 한 후 첫 번째 select()
연결에서는 차단하지 않고 종료되며 준비된 작업이있는 키가 없습니다. 나는 왜 Java가 이런 식으로 행동하는지 모르겠지만, 많은 사람들 이이 행동에 물린 것 같습니다.
결과는 Windows XP의 Sun의 JVM 1.5.0_06과 Linux 2.6의 Sun의 JVM 1.5.0_05 및 1.4.2_04에서 동일합니다.
다른 팁
그 이유는 OP_CONNECT
고 OP_WRITE
은 동일한 것을 후드,그래서 당신은 결코에 등록시(ditto OP_ACCEPT
고 OP_READ
고),당신은 등록 OP_CONNECT
에서 모든 채널은 이미 연결되어 있는,그것이 이 경우에는,가 받아들여집니다.
고 OP_WRITE
은 거의 항상 준비하는 경우를 제외하고 소켓을 보낼 버퍼 e 커널은 전체,그래서 당신이해야만 등록에 대한 후에 당신을 얻을 제 길이 작성합니다.그래서 등록하여 이미 연결되어 있는 채널 OP_CONNECT,
당신이 정말 등록 OP_WRITE,
는 준비가 되어 있었고,그렇게 select()
가 트리거됩니다.