Java Language
NIO - Redes
Buscar..
Observaciones
SelectionKey
define las diferentes operaciones e información seleccionables entre su Selector y Canal . En particular, el archivo adjunto se puede utilizar para almacenar información relacionada con la conexión.
El manejo de OP_READ
es bastante sencillo. Sin embargo, se debe tener cuidado al tratar con OP_WRITE
: la mayoría de las veces, los datos se pueden escribir en sockets para que el evento se siga disparando. Asegúrese de registrar OP_WRITE
solo antes de que desee escribir datos (vea esa respuesta ).
Además, OP_CONNECT
debe cancelarse una vez que el Canal se haya conectado (porque, bueno, está conectado. Vea esto y lo que responde en SO). Por lo tanto, la eliminación de OP_CONNECT
después de finishConnect()
tuvo éxito.
Usando Selector para esperar eventos (ejemplo con OP_CONNECT)
NIO apareció en Java 1.4 e introdujo el concepto de "Canales", que se supone que son más rápidos que la E / S normal. En cuanto a la red, el SelectableChannel
es el más interesante, ya que permite monitorear diferentes estados del Canal. Funciona de manera similar a la llamada al sistema C select()
: nos despertamos cuando ocurren ciertos tipos de eventos:
- conexión recibida (
OP_ACCEPT
) - conexión realizada (
OP_CONNECT
) - Datos disponibles en lectura FIFO (
OP_READ
) - los datos se pueden
OP_WRITE
para escribir FIFO (OP_WRITE
)
Permite la separación entre la detección de E / S de socket (algo se puede leer / escribir / ...) y realizar la E / S (leer / escribir / ...). Especialmente, toda la detección de E / S se puede hacer en un solo subproceso para múltiples sockets (clientes), mientras que la realización de E / S se puede manejar en un conjunto de subprocesos o en cualquier otro lugar. Eso permite que una aplicación se adapte fácilmente al número de clientes conectados.
El siguiente ejemplo muestra lo básico:
- Crear un
Selector
- Crear un
SocketChannel
- Registrar el
SocketChannel
alSelector
- Bucle con el
Selector
para detectar eventos.
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");
Daría la siguiente salida:
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