Frage

einige Testcode Beim Schreiben habe ich festgestellt, dass Selector.select () ohne Selector.selectedKeys zurückkehren können () alle Schlüssel enthält, zu verarbeiten. Dies wird in einer engen Schleife passiert, wenn ich einen accept () ed Kanal mit

registrieren
SelectionKey.OP_READ | SelectionKey.OP_CONNECT

wie die Operationen von Interesse.

Nach der Dokumentation, wählen Sie () sollte zurückgeben, wenn:

1) Es gibt Kanäle, die befolgt werden können.

2) Sie rufen explizit Selector.wakeup () - keine Tasten ausgewählt werden

.

3) Sie ausdrücklich Thread.interrupt () der Thread die Auswahl tun (.) - keine Taste ausgewählt

Wenn ich keine Schlüssel nach dem select get () ich in Fällen sein muss (2) und (3). Allerdings ist mein Code nicht Aufruf Wakeup () oder unterbrechen (), um diese Erträge zu initiieren.

Alle Ideen, was dieses Verhalten verursacht?

War es hilfreich?

Lösung

Kurze Antwort:. Entfernen OP_CONNECT aus der Liste der Operationen, die Sie interessiert sind für die akzeptierte Verbindung - eine akzeptierte Verbindung ist bereits verbunden

habe ich es geschafft, das Problem zu reproduzieren, was genau sein könnte, was mit Ihnen geschieht:

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());
  }
}

Nachdem der obige Server eine Verbindung erhält, der erste select() auf der Verbindung beendet, ohne zu blockieren und es gibt keine Tasten mit bereit Operationen. Ich weiß nicht, warum Java auf diese Weise verhält, aber es scheint, bekommen viele Menschen von diesem Verhalten gebissen.

Das Ergebnis ist das gleiche auf der Sun JVM 1.5.0_06 unter Windows XP sowie Sun JVM 1.5.0_05 und 1.4.2_04 unter Linux 2.6.

Andere Tipps

Der Grund dafür ist, dass OP_CONNECT und OP_WRITE dasselbe unter der Haube sind, so dass Sie nie für beide gleichzeitig (dito OP_ACCEPT und OP_READ) registriert werden sollen, und Sie sollten nie überhaupt für OP_CONNECT registriert werden, wenn der Kanal bereits verbunden ist, , wie es in diesem Fall ist, akzeptiert wurde.

Und OP_WRITE ist fast immer bereit, mit der Ausnahme, wenn die Socket-Sendepuffer in e-Kernel voll ist, so sollten Sie nur für dieses Register, nachdem Sie eine Länge von Null schreiben zu bekommen. So durch den bereits angeschlossenen Kanal für OP_CONNECT, Registrierung Sie waren wirklich für OP_WRITE, Registrierung, die bereit war, so select() ausgelöst wurde.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top