Recherche…


Remarques

SelectionKey définit les différentes opérations et informations sélectionnables entre son sélecteur et son canal . En particulier, la pièce jointe peut être utilisée pour stocker des informations liées à la connexion.

La gestion de OP_READ est assez simple. Cependant, vous devez faire attention lorsque vous traitez avec OP_WRITE : la plupart du temps, les données peuvent être écrites sur les sockets pour que l'événement continue à se déclencher. Assurez-vous d'enregistrer OP_WRITE uniquement avant de vouloir écrire des données (voir cette réponse ).

En outre, OP_CONNECT doit être annulé une fois que le canal est connecté (car, bien, il est connecté. Voir ceci et cela répond sur SO). D' où l' OP_CONNECT enlèvement après finishConnect() a réussi.

Utilisation du sélecteur pour attendre les événements (exemple avec OP_CONNECT)

NIO est apparu dans Java 1.4 et a introduit le concept de "canaux", censés être plus rapides que les E / S classiques. Du point de vue du réseau, le SelectableChannel est le plus intéressant car il permet de surveiller différents états du canal. Il fonctionne de la même manière que l’appel système C select() : nous sommes réveillés lorsque certains types d’événements se produisent:

  • connexion reçue ( OP_ACCEPT )
  • connexion réalisée ( OP_CONNECT )
  • données disponibles en lecture FIFO ( OP_READ )
  • les données peuvent être poussées pour écrire FIFO ( OP_WRITE )

Il permet la séparation entre la détection des E / S de socket (quelque chose peut être lu / écrit / ...) et l' exécution des E / S (lecture / écriture / ...). En particulier, toutes les détections d'E / S peuvent être effectuées dans un seul thread pour plusieurs sockets (clients), tandis que l'exécution d'E / S peut être gérée dans un pool de threads ou ailleurs. Cela permet à une application de s'adapter facilement au nombre de clients connectés.

L'exemple suivant montre les bases:

  1. Créer un Selector
  2. Créer un SocketChannel
  3. Enregistrez le SocketChannel sur le Selector
  4. Boucle avec le Selector pour détecter les événements
Selector sel = Selector.open(); // Create the Selector
SocketChannel sc = SocketChannel.open(); // Create a SocketChannel
sc.configureBlocking(false); // ... non blocking
sc.setOption(StandardSocketOptions.SO_KEEPALIVE, true); // ... set some options

// Register the Channel to the Selector for wake-up on CONNECT event and use some description as an attachement
sc.register(sel, SelectionKey.OP_CONNECT, "Connection to google.com"); // Returns a SelectionKey: the association between the SocketChannel and the Selector
System.out.println("Initiating connection");
if (sc.connect(new InetSocketAddress("www.google.com", 80)))
    System.out.println("Connected"); // Connected right-away: nothing else to do
else {
    boolean exit = false;
    while (!exit) {
        if (sel.select(100) == 0) // Did something happen on some registered Channels during the last 100ms?
            continue; // No, wait some more
        
        // Something happened...
        Set<SelectionKey> keys = sel.selectedKeys(); // List of SelectionKeys on which some registered operation was triggered
        for (SelectionKey k : keys) {
            System.out.println("Checking "+k.attachment());
            if (k.isConnectable()) { // CONNECT event
                System.out.print("Connected through select() on "+k.channel()+" -> ");
                if (sc.finishConnect()) { // Finish connection process
                    System.out.println("done!");
                    k.interestOps(k.interestOps() & ~SelectionKey.OP_CONNECT); // We are already connected: remove interest in CONNECT event
                    exit = true;
                } else
                    System.out.println("unfinished...");
            }
            // TODO: else if (k.isReadable()) { ...
        }
        keys.clear(); // Have to clear the selected keys set once processed!
    }
}
System.out.print("Disconnecting ... ");
sc.shutdownOutput(); // Initiate graceful disconnection
// TODO: emtpy receive buffer
sc.close();
System.out.println("done");

Donnerait la sortie suivante:

Initiating connection
Checking Connection to google.com
Connected through 'select()' on java.nio.channels.SocketChannel[connection-pending remote=www.google.com/216.58.208.228:80] -> done!
Disconnecting ... done


Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow