43

Introducción Características de la nueva API E/S antes de Java 1.4 ¿Por qué NIO? E/S orientada a bloques El patrón Reactor Canales y Buffers Lectura y

Embed Size (px)

Citation preview

Page 1: Introducción Características de la nueva API E/S antes de Java 1.4 ¿Por qué NIO? E/S orientada a bloques El patrón Reactor Canales y Buffers Lectura y
Page 2: Introducción Características de la nueva API E/S antes de Java 1.4 ¿Por qué NIO? E/S orientada a bloques El patrón Reactor Canales y Buffers Lectura y

Introducción Características de la nueva API E/S antes de Java 1.4 ¿Por qué NIO? E/S orientada a bloques El patrón Reactor Canales y Buffers Lectura y escritura en NIO Entendiendo el comportamiento de un buffer Mas sobre buffers File lockings Networking y E/S asincrónica Character sets

Page 3: Introducción Características de la nueva API E/S antes de Java 1.4 ¿Por qué NIO? E/S orientada a bloques El patrón Reactor Canales y Buffers Lectura y

La API NIO (java.nio) es introducida en Java 1.4

Suplementa las facilidades de la API IO (java.io)

Provee nuevas características y mejora la performance en las áreas de:

₋ Manejo de buffers₋ Networking escalable₋ Entrada/Salida de archivos₋ Soporte de “character sets”₋ Expresiones regulares

Page 4: Introducción Características de la nueva API E/S antes de Java 1.4 ¿Por qué NIO? E/S orientada a bloques El patrón Reactor Canales y Buffers Lectura y

Buffers para datos de tipos primitivos

Codificadores y decodificadores de “Character-sets”

Facilidad de “pattern-matching” basada en expresiones regulares estilo Perl

Interface de archivo que soporta bloqueos y mapeo de memoria

Facilidad de entrada salida multiplexada, no bloqueante, para implementar servidores escalables

Page 5: Introducción Características de la nueva API E/S antes de Java 1.4 ¿Por qué NIO? E/S orientada a bloques El patrón Reactor Canales y Buffers Lectura y

Única forma de manipular E/S era mediante la abstracción de flujos (Streams), y sus versiones especializadas para caracteres Unicode (Readers y Writers)

Movimientos de bytes simples, uno a la vez, a través de objetos Stream

Un flujo de entrada “InputStream” produce un byte de datos

Un flujo de salida “OutputStream” consume un byte de datos

Page 6: Introducción Características de la nueva API E/S antes de Java 1.4 ¿Por qué NIO? E/S orientada a bloques El patrón Reactor Canales y Buffers Lectura y

Ejemplo 1₋ Cliente/Servidor₋ Operaciones

bloqueantes

Ejemplo 2₋ Usar Threads para

permitir escalar₋ Problema: Thread

overhead

Page 7: Introducción Características de la nueva API E/S antes de Java 1.4 ¿Por qué NIO? E/S orientada a bloques El patrón Reactor Canales y Buffers Lectura y

Implementación de E/S de alta velocidad sin necesidad de escribir código nativo

NIO traslada la mayoría de las operaciones “pesadas” (manejo de buffers) de E/S al sistema operativo

IO ha sido reimplementada utilizando NIO

Page 8: Introducción Características de la nueva API E/S antes de Java 1.4 ¿Por qué NIO? E/S orientada a bloques El patrón Reactor Canales y Buffers Lectura y

Criterio principal en el diseño de la API NIO

Las aplicaciones servidor en un sistema distribuido deben manejar múltiples clientes enviando pedidos de servicio concurrentes

Previo a la invocación de un servicio, el servidor debe despachar cada pedido entrante al servicio correspondiente (en forma concurrente)

El patrón Reactor resuelve esta funcionalidad

Principales funcionalidades del patrón Reactor₋ Despachar eventos a manejadores de eventos

Page 9: Introducción Características de la nueva API E/S antes de Java 1.4 ¿Por qué NIO? E/S orientada a bloques El patrón Reactor Canales y Buffers Lectura y
Page 10: Introducción Características de la nueva API E/S antes de Java 1.4 ¿Por qué NIO? E/S orientada a bloques El patrón Reactor Canales y Buffers Lectura y

Objetos centrales de la API

Usados prácticamente en todas las operaciones de E/S

Canales (Channel)₋ Análogos a Streams en el paquete IO₋ Todos los datos deben pasar por un canal

Buffers

Page 11: Introducción Características de la nueva API E/S antes de Java 1.4 ¿Por qué NIO? E/S orientada a bloques El patrón Reactor Canales y Buffers Lectura y

Un Buffer es un objeto contenedor de datos sobre el que se escriben, o del que se leen, datos

En NIO todos los datos son manejados con Buffers

Esencialmente es una secuencia (generalmente de bytes, pero puede ser de otro tipo), que provee acceso estructurado a los datos

Page 12: Introducción Características de la nueva API E/S antes de Java 1.4 ¿Por qué NIO? E/S orientada a bloques El patrón Reactor Canales y Buffers Lectura y

Un Canal es un objeto del que se pueden leer (o al que se pueden escribir) datos.

Un canal es similar a un stream.

Todos los datos son manejados mediante Buffers.

Nunca se escribe/lee un byte directamente en/de el canal

Los canales son bidireccionales. Los streams son unidireccionales

Tipos de canales₋ Un stream debe ser subclase o bien de InputStream o

bien de OutputStream₋ Un Canal puede ser abierto para lectura, escritura o

ambas

Page 13: Introducción Características de la nueva API E/S antes de Java 1.4 ¿Por qué NIO? E/S orientada a bloques El patrón Reactor Canales y Buffers Lectura y

Lectura de un canal:

₋ Creo un buffer₋ Solicito al canal

que coloque datos en él

Escritura sobre un canal:

₋ Creo un buffer₋ Lleno el buffer

con datos₋ Solicito al canal

que escriba los datos contenidos en el buffer

Page 14: Introducción Características de la nueva API E/S antes de Java 1.4 ¿Por qué NIO? E/S orientada a bloques El patrón Reactor Canales y Buffers Lectura y

Estado₋ Cambian con cada lectura/escritura₋ Permiten que el buffer maneje sus propios

recursos Accessors

₋ get() - Obtiene datos del buffer₋ put() – Escribe datos en el buffer

Page 15: Introducción Características de la nueva API E/S antes de Java 1.4 ¿Por qué NIO? E/S orientada a bloques El patrón Reactor Canales y Buffers Lectura y

Creo un buffer de 8 slots Posiciones válidas 0 a 7 Position = 0 Limit = Capacity = 8

Page 16: Introducción Características de la nueva API E/S antes de Java 1.4 ¿Por qué NIO? E/S orientada a bloques El patrón Reactor Canales y Buffers Lectura y

Leo de un canal (por ejemplo 3 bytes) Position = 3 Limit = Capacity = 8

Page 17: Introducción Características de la nueva API E/S antes de Java 1.4 ¿Por qué NIO? E/S orientada a bloques El patrón Reactor Canales y Buffers Lectura y

Segunda lectura (por ejemplo 2 bytes) Position = 5 Limit = Capacity = 8

Page 18: Introducción Características de la nueva API E/S antes de Java 1.4 ¿Por qué NIO? E/S orientada a bloques El patrón Reactor Canales y Buffers Lectura y

Ejecuto flip() para poder leer del buffer1. Limit = Position = 52. Position = 03. Capacity = 8

Page 19: Introducción Características de la nueva API E/S antes de Java 1.4 ¿Por qué NIO? E/S orientada a bloques El patrón Reactor Canales y Buffers Lectura y

Leo datos del buffer (escribo en un canal) Por ejemplo 4 bytes Limit = 5 Position = 4

Page 20: Introducción Características de la nueva API E/S antes de Java 1.4 ¿Por qué NIO? E/S orientada a bloques El patrón Reactor Canales y Buffers Lectura y

Leo datos del buffer (escribo en un canal) Por ejemplo 1 byte (lo que resta) Limit = 5 Position = 5

Page 21: Introducción Características de la nueva API E/S antes de Java 1.4 ¿Por qué NIO? E/S orientada a bloques El patrón Reactor Canales y Buffers Lectura y

Invoco clear Position = 0 Limit = Capacity = 8

Page 22: Introducción Características de la nueva API E/S antes de Java 1.4 ¿Por qué NIO? E/S orientada a bloques El patrón Reactor Canales y Buffers Lectura y

Accessors en ByteBuffer₋ byte get()₋ ByteBuffer get(byte dst [])₋ ByteBuffer get(byte dst [], int offset, int lenght)₋ byte get(int index)

Los tres primeros son relativos (a position) y modifican el estado (position)

El cuarto es absoluto y no afecta el estado

Page 23: Introducción Características de la nueva API E/S antes de Java 1.4 ¿Por qué NIO? E/S orientada a bloques El patrón Reactor Canales y Buffers Lectura y

put() en ByteBuffer₋ ByteBuffer put(byte b)₋ ByteBuffer put(byte src [])₋ ByteBuffer put(byte src [], int offset, int lenght)₋ ByteBuffer put(ByteBuffer src)₋ ByteBuffer put(int index, byte b)

Los cuatro primeros son relativos (a position) y modifican el estado (position)

El quinto es absoluto y no afecta el estado

Page 24: Introducción Características de la nueva API E/S antes de Java 1.4 ¿Por qué NIO? E/S orientada a bloques El patrón Reactor Canales y Buffers Lectura y

get() y put() tipados₋ getByte()₋ getChar()₋ getShort()₋ getInt()₋ getLong()₋ getFloat()₋ getDouble()₋ putByte()₋ putChar()₋ putShort()₋ putInt()₋ putLong()₋ putFloat()₋ putDouble()

Page 25: Introducción Características de la nueva API E/S antes de Java 1.4 ¿Por qué NIO? E/S orientada a bloques El patrón Reactor Canales y Buffers Lectura y

Asignación de espacio₋ Previo a utilizar un buffer es necesario reservar el

espacio para su contenido₋ Método estático allocate() crea el array interno

ByteBuffer buffer = ByteBuffer.allocate(1024);

Wrapping₋ Es posible convertir un array existente en un

Buffer

byte[] arr = new byte[1024];ByteBuffer buffer = ByteBuffer.wrap(arr);

₋ Cuidado: los datos pueden ser accedidos desde arr !!!

Page 26: Introducción Características de la nueva API E/S antes de Java 1.4 ¿Por qué NIO? E/S orientada a bloques El patrón Reactor Canales y Buffers Lectura y

Slicing₋ El método slice() crea una especie de sub buffer

de un buffer₋ Datos compartidos con una porción del buffer

origen

ByteBuffer buffer = ByteBuffer.allocate( 10 );

for (int i=0; i<buffer.capacity(); ++i) { buffer.put( (byte)i );}

buffer.position(3);buffer.limit(7);ByteBuffer slice = buffer.slice();

Page 27: Introducción Características de la nueva API E/S antes de Java 1.4 ¿Por qué NIO? E/S orientada a bloques El patrón Reactor Canales y Buffers Lectura y

Buffers de solo lectura₋ Usar el método asReadOnlyBuffer() para obtener

una copia de solo lectura del buffer₋ Comparte datos con el buffer original₋ Un buffer de solo lectura no puede convertirse en

un buffer de lectura/escritura

Page 28: Introducción Características de la nueva API E/S antes de Java 1.4 ¿Por qué NIO? E/S orientada a bloques El patrón Reactor Canales y Buffers Lectura y

Scattering/Gattering₋ Lectura/Escritura de un canal usando múltiples

buffers₋ Útil para separar porciones de datos diferentes

(ejemplo: secciones de tamaño fijo en un paquete de un protocolo de red)

Interfaces: ScatteringByteChannel y GatheringByteChannel

Page 29: Introducción Características de la nueva API E/S antes de Java 1.4 ¿Por qué NIO? E/S orientada a bloques El patrón Reactor Canales y Buffers Lectura y

No tiene que ver con prevenir cualquier uso de un archivo

Permite que distintas partes de la aplicación coordinen los archivos compartidos y la adquisición de locks

Se puede bloquear un archivo entero o una parte del mismo

Page 30: Introducción Características de la nueva API E/S antes de Java 1.4 ¿Por qué NIO? E/S orientada a bloques El patrón Reactor Canales y Buffers Lectura y

A continuación, veremos un ejemplo en el cual se intenta abrir un archivo .txt utilizando los bloqueos de archivos.

Page 31: Introducción Características de la nueva API E/S antes de Java 1.4 ¿Por qué NIO? E/S orientada a bloques El patrón Reactor Canales y Buffers Lectura y

E/S asincrónica₋ Una invocación a read() sobre un InputStream bloquea el hilo

actual hasta que hayan datos disponibles

₋ E/S asincrónica no es bloqueante

₋ La aplicación se registra por un evento de E/S particular (disponibilidad de nuevos datos, conexiones de socket, etc.) y el sistema notifica la llegada del evento

₋ Es posible escuchar por eventos en un número arbitrario de canales sin necesidad de polling o hilos extra

Page 32: Introducción Características de la nueva API E/S antes de Java 1.4 ¿Por qué NIO? E/S orientada a bloques El patrón Reactor Canales y Buffers Lectura y

Selectores₋ Es el objeto sobre el

cual registrarse por eventos de E/S

₋ Notifica la ocurrencia de estos eventos

₋ Luego es necesario registrar los canales sobre el selector para notificarnos de la ocurrencia de eventos

http://tutorials.jenkov.com/java-nio/selectors.html

Page 33: Introducción Características de la nueva API E/S antes de Java 1.4 ¿Por qué NIO? E/S orientada a bloques El patrón Reactor Canales y Buffers Lectura y

Abriendo un ServerSocketChannel₋ Objeto que recibe las solicitudes de conexiones

(uno por cada puerto)

El argumento OP_ACCEPT especifica que se va a escuchar por eventos accept (nueva conexión)

Cuando un Selector notifica un evento lo hace proveyendo la SelectionKey que corresponde al evento

La SelectionKey puede ser usada para desregistrar el canal

Page 34: Introducción Características de la nueva API E/S antes de Java 1.4 ¿Por qué NIO? E/S orientada a bloques El patrón Reactor Canales y Buffers Lectura y

El loop interno Notificación de eventos

int num = selector.select();Set selectedKeys = selector.selectedKeys();Iterator it = selectedKeys.iterator();while (it.hasNext()) {

SelectionKey key = (SelectionKey)it.next();

// ... deal with I/O event ...}

Page 35: Introducción Características de la nueva API E/S antes de Java 1.4 ¿Por qué NIO? E/S orientada a bloques El patrón Reactor Canales y Buffers Lectura y

Escuchando por nuevas conexiones

Consulto el tipo de eventoif ((key.readyOps() & SelectionKey.OP_ACCEPT)

== SelectionKey.OP_ACCEPT) {// Accept the new connection// ...

}

Page 36: Introducción Características de la nueva API E/S antes de Java 1.4 ¿Por qué NIO? E/S orientada a bloques El patrón Reactor Canales y Buffers Lectura y

Luego de recibido el evento de solicitud de conexión, se acepta mediante la operación no bloqueante accept()

ServerSocketChannel ssc = (ServerSocketChannel)key.channel();SocketChannel sc = ssc.accept();

Page 37: Introducción Características de la nueva API E/S antes de Java 1.4 ¿Por qué NIO? E/S orientada a bloques El patrón Reactor Canales y Buffers Lectura y

Configuramos en nuevo SocketChannel como “no bloqueante”

Registramos el SocketChannel con el Selector para informarnos de los eventos de llegada de datos (OP_READ)

sc.configureBlocking(false);SelectionKey newKey = sc.register(selector, SelectionKey.OP_READ);

Page 38: Introducción Características de la nueva API E/S antes de Java 1.4 ¿Por qué NIO? E/S orientada a bloques El patrón Reactor Canales y Buffers Lectura y

A continuación, veremos un ejemplo en el cual se establece una conexión. Para ello, se utilizan sockets.

En este caso, según el tipo de la key enviada, la conexión será para escribir, leer, conectarse o aceptar conexión.

Page 39: Introducción Características de la nueva API E/S antes de Java 1.4 ¿Por qué NIO? E/S orientada a bloques El patrón Reactor Canales y Buffers Lectura y

Un Charset es “un mapa nominado entre secuencias de caracteres Unicode de 16 bits y secuencias de bytes”

Permite leer y escribir secuencias de caracteres en la forma mas portable posible

Java se basa en Unicode

No todo se basa en Unicode

Charset permite codificar y decodificar entre distintas representaciones

₋ Ejemplo: Unicode <-> ISO-8859-1

Page 40: Introducción Características de la nueva API E/S antes de Java 1.4 ¿Por qué NIO? E/S orientada a bloques El patrón Reactor Canales y Buffers Lectura y

Ejemplo₋ Se leen los datos de un archivo de texto (ISO-

8859-1) en un CharBuffer (usando un CharsetDecoder)

₋ Se recodifican en UTF16 y se escriben en un nuevo archivo usando un CharsetEncoder

Cualquier implementación de Java debe soportar₋ US-ASCII₋ ISO-8859-1₋ UTF-8₋ UTF-16BE₋ UTF-16LE₋ UTF-16

Page 41: Introducción Características de la nueva API E/S antes de Java 1.4 ¿Por qué NIO? E/S orientada a bloques El patrón Reactor Canales y Buffers Lectura y

A continuación veremos un ejemplo en el cual se quiere convertir bytes ISO-8859-1 en un ByteBuffer, a un string en CharBuffer y viceversa.

Page 42: Introducción Características de la nueva API E/S antes de Java 1.4 ¿Por qué NIO? E/S orientada a bloques El patrón Reactor Canales y Buffers Lectura y

Características de la nueva API E/S antes de Java 1.4 ¿Por qué NIO? E/S orientada a bloques El patrón Reactor Canales y Buffers Lectura y escritura en NIO Entendiendo el comportamiento de un buffer Mas sobre buffers File lockings Networking y E/S asincrónica Character sets

Page 43: Introducción Características de la nueva API E/S antes de Java 1.4 ¿Por qué NIO? E/S orientada a bloques El patrón Reactor Canales y Buffers Lectura y

Getting started with New IO (NIO)Greg TravisIBM Developer workshttp://www-128.ibm.com/developerworks/edu/j-dw-java-nio-i.html

Sun New I/O APIs Guidehttp://java.sun.com/j2se/1.4.2/docs/guide/nio/

Java™ NIORon HitchensO’ReillyISBN: 0-596-00288-2, 312 pages