Tema II: Programaci - PowerPoint PPT Presentation

1 / 91
About This Presentation
Title:

Tema II: Programaci

Description:

Title: PowerPoint Presentation Last modified by: Lunix Lonigan Created Date: 1/1/1601 12:00:00 AM Document presentation format: On-screen Show (4:3) – PowerPoint PPT presentation

Number of Views:362
Avg rating:3.0/5.0
Slides: 92
Provided by: docenciaE3
Category:

less

Transcript and Presenter's Notes

Title: Tema II: Programaci


1
Tema IIProgramación con sockets
  • Luis López Fernández

2
Tema II Contenidos
2.1 Introducción 2.2 Streams en Java 2.3
Sockets TCP 2.4 Sockets UDP 2.5 Sockets con
entrada/salida asíncrona en Java
3
Lección 2.1 Introducción
2.1 Introducción 2.2 Streams en Java 2.3
Sockets TCP 2.4 Sockets UDP 2.5 Sockets con
entrada/salida asíncrona en Java
4
La API de sockets
  • La API de sockets es un mecanismo que permite
    acceder a los servicios IPC proporcionados por
    los protocolos TCP y UDP
  • Los sockets están en el nivel de abstracción del
    modelo de paso de mensajes
  • Casi nadie desarrolla directamente sobre sockets
    hoy en día
  • pero todas las APIs de mayor abstracción se
    basan en sockets
  • Es importante comprender los detalles de la API
    de sockets
  • La API de sockets está disponible en la inmensa
    mayoría de los sistemas
  • En ocasiones forma parte del núcleo del sistema
    operativo (i.e. Unix)
  • En ocasiones es una librería externa (i.e. API
    Winsock de Windows)
  • Traducción de socket
  • enchufe, toma eléctrica
  • La metáfora es que el socket es un punto en el
    proceso (toma) al que otros procesos pueden
    enchufar un cable
  • El cable representa una conexión o un flujo de
    datos

5
La metáfora del socket
Proceso A
Proceso B
6
La metáfora del socket
Proceso A
Proceso B
CREATE SOCKET
CREATE SOCKET
7
La metáfora del socket
Proceso A
Proceso B
PLUG SOCKET
PLUG SOCKET
8
La metáfora del socket
Proceso A
Proceso B
SEND DATA
RECEIVE DATA
9
La metáfora del socket
Proceso A
Proceso B
UNPLUG
UNPLUG
10
Lección 2.2 Streams en Java
2.1 Introducción 2.2 Streams en Java 2.3
Sockets TCP 2.4 Sockets UDP 2.5 Sockets con
entrada/salida asíncrona en Java
11
Streams
  • Traducción de Stream
  • Corriente, chorro, flujo
  • El stream es una secuencia ordenada de unidades
    de información (bytes, caracteres, etc) que puede
    fluir en dos direcciones hacia fuera de un
    proceso (de salida) o hacia dentro de un proceso
    (de entrada)
  • Los streams están diseñados para acceder a los
    datos de manera secuencial
  • Los streams no suelen estar preparados para
    realizar operaciones no secuenciales (volver
    hacia atrás, saltarse datos, realizar acceso
    aleatorio a datos, etc.)
  • Los streams, en principio, van recorriendo una
    secuencia de datos (de entrada o de salida) y al
    mismo tiempo, la van consumiendo. Es decir, un
    dato leido/escrito no puede ser
    desleido/desecrito (nota existen excepciones a
    esta regla)
  • Pueden existir streams especializados en la
    lectura/escritura de determinados tipos de datos
    (bytes, enteros, flotantes, caracteres, objetos,
    etc.)

12
Funcionamiento básico de un stream
Proceso
E l g a t o e s p e r ó u n r a t o , p e
Secuencia de bytes almacenados en un fichero
13
Funcionamiento básico de un stream
OPEN STREAM
E l g a t o e s p e r ó u n r a t o , p e
Secuencia de bytes almacenados en un fichero
14
Funcionamiento básico de un stream
READ BYTE
E
E l g a t o e s p e r ó u n r a t o , p e
Secuencia de bytes almacenados en un fichero
15
Funcionamiento básico de un stream
READ BYTE
El
E l g a t o e s p e r ó u n r a t o , p e
Secuencia de bytes almacenados en un fichero
16
Funcionamiento básico de un stream
READ BYTE
El_
E l g a t o e s p e r ó u n r a t o , p e
Secuencia de bytes almacenados en un fichero
17
Funcionamiento básico de un stream
READ BYTE
El_g
E l g a t o e s p e r ó u n r a t o , p e
Secuencia de bytes almacenados en un fichero
18
Funcionamiento básico de un stream
READ BYTE
El_ga
E l g a t o e s p e r ó u n r a t o , p e
Secuencia de bytes almacenados en un fichero
19
Funcionamiento básico de un stream
CLOSE STREAM
El_ga
E l g a t o e s p e r ó u n r a t o , p e
Secuencia de bytes almacenados en un fichero
20
Streams, Readers y Writers en Java
  • En informática, existen dos mecanismos
    fundamentales para almacenar datos
  • En formato texto
  • Utiliza el carácter como unidad de almacenamiento
  • El carácter es la representación de un símbolo
    legible por un humano
  • En formato binario
  • Utiliza el byte como unidad de almacenamiento
  • Este formato no es, en general, legible por
    humanos
  • En Java, existen clases especialistas para
    leer/escribir datos en estos formatos
  • Lectura de streams de texto Reader
  • Escritura en steams de texto Writer
  • Lectura de streams binarios InputStream
  • Escritura en streams binarios OutputStream
  • Las cuatro clases mencionadas son abstractas (no
    se pueden instanciar directamente objetos de esa
    clase)
  • Cada una de esas cuatro clases actúa como padre
    de una jerarquía de herencia
  • En la citada jerarquía se han definido clases
    concretas especialistas en problemas concretos
    de entrada/salida de datos
  • Todas las clases de la jerarquía forman parte del
    paquete java.io de la API estándar

21
Jerarquía de herencia asociada a InputStream
22
Jerarquía de herencia asociada a OutputStream
23
Jerarquía de herencia asociada a Reader
24
Jerarquía de herencia asociada a Writer
25
Leyendo y escribiendo datos binarios con Streams
package es.urjc import java.io. public class
BasicDataStreams //Los datos que vamos a
escribir en un fichero private static byte
primes 1, 2, 3, 5, 7, 11, 13 public
static void readDataFile(String filename) throws
IOException FileInputStream fis new
FileInputStream(filename) int prime while(
(prime fis.read()) ! -1) System.out.println(
"He leido " (byte)prime) fis.close() p
ublic static void writeDataFile(String filename)
throws IOException File file new
File(filename) FileOutputStream fos new
FileOutputStream(file) for(int i 0 i lt
primes.length i) fos.write(primesi) f
os.flush() fos.close() ...
26
Leyendo y escribiendo datos binarios con Streams
package es.urjc import java.io. public class
BasicDataStreams ... public static void
main(String args) String filename
"primes.dat" if(args.length 1) filename
args0 try writeDataFile(filename)
catch(IOException ioe) System.err.println("
No se ha podido escribir en el fichero "
filename) try readDataFile(filename)
catch(IOException ioe) System.err.println(
"No se ha podido escribir en el fichero "
filename)
27
Conectando streams para realizar entrada/salida
  • Cada tipo de stream es especialista en un tipo de
    entrada/salida
  • Por ejemplo
  • FileInputSteam especialista en leer bytes de un
    fichero
  • DataInputStream especialista en leer datos
    complejos (enteros, flotantes, booleanos, etc.)
    de un stream de bytes
  • Los streams se pueden conectar para combinar
    sus capacidades

Especialista en leer datos complejos de streams
de bytes
Fichero en disco
Especialista en leer bytes de ficheros
Datos leídos
0101 1001 1101
1,234 0,2345 2,23E-12
doubles
bytes
Hw
... FileInputStream fis new FileInputStream("C\
\nombre\\fichero.dat") DataInputStream dis new
DataInputStream(fis) dis.readInt() dis.readFloat
() dis.readDouble() dis.close() ...
28
Serialización y streams de objetos
  • Los DataStreams son especialistas en algunos
    datos complejos (int, double, etc.)
  • Los ObjectStreams son especialistas en
    leer/escribir objetos en/desde streams
  • Los ObjectStreams se basan en el mecanismo de la
    serialización
  • En Java, la serialización es el proceso por el
    que un objeto se transforma en una secuencia de
    bytes que lo representa
  • La deserialización es proceso por el que se
    reconstruye un objeto previamente serializado a
    partir de una secuencia de bytes
  • En Java, para que un objeto sea serializable,
    debe ser instancia de una clase que implemente la
    interfaz Serializable, esta interfaz no define
    ningún método

class MiClase implements Serializable
//atributos y métodos ... MiClase miObjeto
new MiClase()
Objeto en memoria
Objeto recuperado en memoria
Serialización
Deserialización
value 14 name Hello p0.23
value 14 name Hello p0.23
Objeto serializado
001010100010101
29
ObjectIntputStream y ObjectOutputStream
  • ObjectOutputStream
  • Especialista en transformar objetos en una
    secuencia de bytes (en serializar objetos)
  • Debe estar conectado a un OutputStream que se
    especifica en construcción
  • Ej ObjectOutputStream oos new
    ObjectOutputStream(outputStream)
  • La serialización se realiza invocando el método
    void writeObject (Object obj)
  • ObjectInputStream
  • Especialista en recuperar objetos desde una
    secuencia de bytes (en recuperar objetos
    previamente serializados)
  • Debe estar conectado a un InputStream que se
    especifica en construcción
  • Ej ObjectInputStream ois new
    ObjectInputStream(inputStream)
  • La deserialización se logra invocando el método
    Object readObject()

Ejemplo de clase serializable
import java.util.ArrayList public class Persona
implements Serializable public String
nombre public int age public
ArrayListltPersonagt friends
30
Ejemplo de uso de Object/Input/Output/Streams
import java.io. public class BasicObjectStreams
private static void writePersona(String
filename) Persona p new Persona() p.name
"Luis" p.age 29 p.friends
null try ObjectOutputStream oos new
ObjectOutputStream(new FileOutputStream(file
name)) oos.writeObject(p) oos.close()
catch(IOException ioe ) System.exit(-1)
private static Persona readPersona(String
filename) try ObjectInputStream ois new
ObjectInputStream(new FileInputStream(filena
me)) return (Persona)ois.readObject()
//Habría que cerrar con close()
catch(IOException ioe) System.err.println(ioe
.getMessage()) catch (ClassNotFoundException
cnfe) cnfe.printStackTrace() return
null ...
31
Ejemplo de uso de Object/Input/Output/Streams
import java.io. public class
BasicObjectStreams ... public static void
main(String args) String filename
"persona.dat" if(args.length 1) filename
args0 writePersona(filename) Persona p
readPersona(filename) System.out.println("p.n
ame" p.name " -- p.age" p.age)
javac BasicObjectStreams.java java
BasicObjectStream p.nameLuis -- p.age29 ls
... persona.dat
32
Qué se serializa?
  • Los objetos que sean instancias de clases
    Serializable se pueden serializar
  • Para que un atributo no se serialice, debe ser
    marcado como transient
  • Multitud de atributos no pueden ser serializados
    y deben ser marcados como transient (por ejemplo,
    un FileInputStream)
  • Se serializan todos los atributos que no sean
    transient ni static
  • Si un atributo es una referencia a un objeto, el
    objeto se serializa
  • Por tanto, la serialización de un objeto con
    referencias crea un árbol de serialización
  • Al deserializar el objeto, se recupera el árbol
    completo de objetos
  • Si hay varias referencias a un objeto, los datos
    del mismo se serializan solo una vez

Objeto A
Objeto B
Objeto A
Objeto B
Objeto D
Objeto D
transient
Serialización Objeto A
Deserialización Objeto A
001010110
Objeto C
Objeto E
Objeto E
33
Readers, writers y charsets
  • La entrada/salida de caracteres de texto es
    compleja debido a la gran cantidad de formatos de
    codificación que existen (ASCII, UTF-8, Unicode,
    etc.)
  • Hacer entrada/salida de texto directamente con
    streams es complejo
  • Los Readers y los Writers simplifican enormemente
    la tarea
  • Como en el caso de los streams, existen clases
    especialistas en tareas concretas
  • Para entenderlas hay que comprender cómo Java
    procesa y representa caracteres
  • En Java, los caracteres se representan
    internamente en formato Unicode de 16 bits
  • Cuando se lee un carácter, este se convierte de
    su formato nativo a Unicode
  • Cuando se escribe un carácter, este se convierte
    de Unicode a su formato objetivo
  • En Java, al formato nativo/objetivo de una cadena
    se le denomina su charset
  • Desde Java 1.5 existe la clase Charset (en el
    paquete java.nio.charset) que permite operar
    sobre la representación de caracteres
  • En Java, se soportan múltiples charsets de
    entrata/salida, entre los que se incluyen
    US-ASCII, ISO-8859-1, UTF-8, UTF-16BE, UTF-816LE,
    etc.
  • Cada instancia de la máquina virtual tiene un
    charset por defecto que depende del formato
    utilizado por el sistema operativo subyacente
  • El charset por defecto se puede averiguar
    mediante el método estático defaultCharset() de
    la clase Charset

34
Algunos Readers y Writers
  • Vamos a ver algunos Readers y Writers básicos y
    en qué se especializan
  • InputStreamReader
  • Hace de puente entre streams de bytes y de
    caracteres
  • Debe estar conectado con un InputStream que se
    especifica en construcción
  • Tiene constructores que permiten especificar un
    Charset de preferencia
  • Los constructores que no toman un Charset, usan
    el charset por defecto
  • Puede leer caracteres de uno en uno utilizando el
    método int read()
  • OutputStreamWriter
  • Equivalente al InputStreamReader pero para salida
    de caractéres
  • Escribe caractéres usando el método write(int c)

Hijos de InputStream
chars
bytes
Hijos de OutputStream
chars
bytes
35
Algunos Readers y Writers
  • BufferedReader
  • Permite leer texto de forma eficiente a través de
    un buffer intermedio
  • Debe estar conectado con un Reader que se
    especifica en construcción
  • Se utiliza el Charset que posea ese Reader
  • Puede leer líneas completas utilizando el método
    String readLine()
  • PrintWriter
  • Imprime texto formateado
  • Puede estar conectado a un Writer
  • Puede estar conectado a un OutputStream
  • Puede volcar directamente sobre un fichero
  • Existen constructores para cada uno de los casos
  • Se pueden imprimir líneas completas usando el
    método println(String line)

InputStreamReader isr new InputStreamReader(new
FileOutputStream(C\\file.txt) BufferedReader
br new BufferedReader(isr) String line
br.readLine() ... PrintWriter pw new
PrintWriter(C\\file.txt) pw.println(Hola
mundo) ...
36
Lección 2.3 Sockets TCP
2.1 Introducción 2.2 Streams en Java 2.3
Sockets TCP 2.4 Sockets UDP 2.5 Sockets con
entrada/salida asíncrona en Java
37
La API de sockets en modo stream (TCP sockets)
  • La API de sockets en modo stream proporciona
    acceso al servicio de transporte de datos
    proporcionado por el protocolo TCP
  • El servicio TCP es orientado a conexión
    proporciona un transporte fiable
  • La conexión se establece
  • Un flujo de bytes sale del emisor
  • El mismo flujo de bytes es recibido en el
    receptor
  • El servicio proporcionado por el socket es
    full-duplex (el mismo socket puede ser utilizado
    para enviar y para recibir datos)
  • Para que la conexión se pueda establecer,
  • Uno de los sockets debe estar a la espera de
    recibir conexiones
  • El otro socket debe iniciar una conexión
  • Para que una conexión se libere (cierre)
  • Basta con que uno de los sockets desee cerrarla
  • Un socket recién creado no está conectado
  • Vamos a estudiar en detalle el funcionamiento de
    los sockets TCP utilizando la funcionalidad
    proporcionada por la API estándar de Java

38
Tipos de stream socket en Java
  • En Java hay dos tipos de stream sockets que
    tienen asociadas sendas clases
  • ServerSocket
  • Proporciona un socket dispuesto a aceptar
    conexiones TCP de forma pasiva
  • Para simplificar, lo denominaremos socket de
    conexión
  • Al proceso que posee un ServerSocket se le
    denomina también servidor
  • Socket
  • Proporciona un socket por el que se pueden
    intercambiar datos con otro socket
  • Para simplificar, lo denominaremos socket de
    datos
  • Al proceso que inicia una conexión desde un
    Socket se le denomina cliente
  • El proceso a seguir para lograr el intercambio de
    datos es
  • El servidor crea el ServerSocket y lo asocia a un
    puerto
  • El cliente crea un Socket
  • El cliente ordena a su Socket que se conecte con
    el ServerSocket remoto
  • Al recibir la petición, el servidor crea un nuevo
    Socket y lo connecta con el remoto
  • Se intercambian los datos
  • La conexión se cierra cuando alguno de los dos
    sockets lo indica

39
La clase ServerSocket
  • La clase ServerSocket forma parte del paquete
    java.net de la API estándar
  • Constructores
  • ServerSocket() Crea un nuevo socket de conexión
    no atado a ningún puerto
  • ServerSocket(int port) Crea un nuevo socket de
    conexión y lo ata al puerto especificado. En
    número de puerto debe estar comprendido entre 0 y
    65535 inclusive. Si port es 0, se toma un puerto
    libre al azar
  • ServerSocket(int port, int backlog) Permite
    además especificar el tamaño de la cola de
    solicitudes de conexión no atendidas. Si el
    número de solicitudes no atendidas supera el
    tamaño especificado se rechazán solicitudes de
    conexión
  • ServerSocket(int port, int backlog, InetAddress
    bindAddr) Permite además especificar la
    dirección IP en la que se atenderán las
    solicitudes de conexión (para ordenadores que
    dispongan de varias). Si bindAddr es null, el
    ServerSocket atenderá solicitudes de conexión en
    todas las interfaces de la máquina

40
La clase ServerSocket Cont.
Algunos Métodos Socket accept() Escucha una
solicitud de conexión y la acepta cuando se
recibe. En ese momento, se crea nuevo Socket que
es el que realmente se conecta con el cliente.
Tras esto, el ServerSocket sigue disponible para
realizar nuevos accept() void bind(SocketAddress
endpoint) Ata al ServerSocket a la dirección
especificada (dirección IP y puerto). El
ServerSocket no debe estar atado previamente int
getLocalPort() Devuelve el puerto al que está
atado el ServerSocket void close() Cierra el
ServerSocket
... ServerSocket serverSocket new
ServerSocket(0) System.out.println(El puerto es
serverSocket.getLocalPort()) Socket
connection serverSocket.accept() //hacemos
cosas con connection Socket otherConnection
serverSocket.accept() //hacemos cosas con
otherConnection serverSocket.close() ...
41
La clase Socket
  • La clase Socket forma parte del paquete java.net
    de la API estándar
  • Algunos Constructores
  • Socket() Crea un nuevo socket sin conectar
  • Socket(InetAddress address, int port) Crea un
    nuevo socket y lo conecta automáticamente con un
    socket remoto en la dirección IP y puertos
    especificados
  • Socket(InetAddress address, int port, InetAddress
    localAddr, int localPort) Permite además
    especificar la dirección IP local y el puerto
    local a los que se asociará el socket
  • Socket(String host, int port) El host remoto se
    puede especificar a través de su nombre de
    dominio. Se utilizarán los mecanismos de
    resolución del sistema operativo subyacente
  • Socket(Proxy proxy) Se crea un socket no
    conectado especificando el tipo de proxy que se
    desea usar

42
La clase Socket Cont.
Algunos Métodos void connect(SocketAddress
endpoint) Conecta este socket al servidor
especificado (dirección IP y puerto) InetAddress
getInetAddress() Devuelve la dirección (IP y
puerto) a la que este socket se encuentra
conectado InputStream getInputStream() Devuelve
un InputStream que permite leer bytes del socket
(recibir datos enviados desde el socket remoto)
utilizando los mecanismos habituales de los
streams. El socket debe estar conectado OutputStre
am getOutputStream() Devuelve un OutputStream
que permite escribir bytes sobre el socket
(enviar bytes al socket remoto) utilizando los
mecanismos habituales de los streams. El socket
debe estar conectado void setKeepAlive() Al
activarlo, se chequea que la conexión entre dos
sockets sigue activa enviando paquetes basura
periódicamente (RFC 1122) void setSoLinger(boolean
on, int linger) Al activarlo, si hay datos
pendientes de enviar cuando se invoca close(), el
llamante se bloquea (durante un máximo de linger
segundos) hasta que los datos pendientes han sido
enviados void setTcpNoDelay() Permite
activar/desactivar el algoritmo de Nagle para el
envío en TCP (RFC 896) void setTrafficClass(int
tc) Permite seleccionar el byte TOS del paquete
IP (no todas las redes lo tienen en cuenta) Más
información en RFC 1349
43
Sincronización de cliente y servidor
Cliente
Servidor
server new ServerSocket()
server.accept()
client new Socket(host, port)
Conexión
Nuevo Socket conectado
read() sobre el Socket
write() sobre el socket
Mensaje
read() sobre el socket
write() sobre el Socket
Mensaje
socket.close()
socket.close()
serverSocket.close()
44
Sincronización de cliente y servidor
Cliente
Servidor
server new ServerSocket()
server.accept()
client new Socket(host, port)
Conexión
Nuevo Socket conectado
read() sobre el Socket
write() sobre el socket
Mensaje
read() sobre el socket
write() sobre el Socket
ServerSocket server new ServerSocket() La
creación del ServerSocket no requiere
ninguna sincronización entre servidor y cliente,
la operación es no -bloqueante
Mensaje
socket.close()
socket.close()
serverSocket.close()
45
Sincronización de cliente y servidor
Cliente
Servidor
server new ServerSocket()
server.accept()
client new Socket(host, port)
Conexión
Nuevo Socket conectado
read() sobre el Socket
write() sobre el socket
Mensaje
read() sobre el socket
write() sobre el Socket
Socket socket serverSocket.accept() La llamada
a accept() es síncrona y bloquea al hilo
llamante hasta que se recibe una solicitud de
conexión destinada al proceso servidor (dirección
IP y puerto). Cuando se recibe la citada
solicitud, se crea un nuevo socket que sirve
como extremo de la conexión junto con el socket
remoto del cliente
Mensaje
socket.close()
socket.close()
serverSocket.close()
46
Sincronización de cliente y servidor
Cliente
Servidor
server new ServerSocket()
server.accept()
client new Socket(host, port)
Conexión
Nuevo Socket conectado
read() sobre el Socket
write() sobre el socket
Mensaje
read() sobre el socket
write() sobre el Socket
Socket client new Socket(host, port) La
creación del socket cliente con este constructor
requiere el establecimiento de la conexión,
motivo por el cual esta llamada es bloqueante,
haciendo que el hilo cliente se bloquee hasta que
el establecimiento de la conexión haya
finalizado.
Mensaje
socket.close()
socket.close()
serverSocket.close()
47
Sincronización de cliente y servidor
Cliente
Servidor
server new ServerSocket()
server.accept()
client new Socket(host, port)
Conexión
Nuevo Socket conectado
read() sobre el Socket
write() sobre el socket
Mensaje
read() sobre el socket
write() sobre el Socket
socket.getInputStream()?read() La llamada a
read() sobre el InputStream del socket
es bloqueante, el hilo se detiene mientras no se
reciban los datos enviados por el proceso remoto.
Si se especifica un tamaño de datos esperado, la
llamada se bloquea hasta que se
reciben suficiente información desde el socket
remoto (i.e. readLine())
Mensaje
socket.close()
socket.close()
serverSocket.close()
48
Sincronización de cliente y servidor
Cliente
Servidor
server new ServerSocket()
server.accept()
client new Socket(host, port)
Conexión
Nuevo Socket conectado
read() sobre el Socket
write() sobre el socket
Mensaje
read() sobre el socket
write() sobre el Socket
socket.getOutputStream()?write() La llamada a
write() sobre el OutputStream del socket
es bloqueante, el hilo se detiene mientras TCP
haya recibido el asentimiento de los datos
enviados. Puede que una llamada a write() se
desbloquee sin que se haya producido un read()
en el proceso remoto, pero esto sólo sucede
cuando los datos enviados caben en la ventana
TCP del receptor
Mensaje
socket.close()
socket.close()
serverSocket.close()
49
Sincronización de cliente y servidor
Cliente
Servidor
server new ServerSocket()
server.accept()
socket.close() Las llamadas a cloase() son
siempre no-bloqueantes, excepto cuando SO_LINGER
se ha activado sobre el socket, En cuyo caso la
llamada es bloqueante hasta que se terminan de
enviar los datos pendientes
client new Socket(host, port)
Conexión
Nuevo Socket conectado
read() sobre el Socket
write() sobre el socket
Mensaje
read() sobre el socket
write() sobre el Socket
Mensaje
socket.close()
socket.close()
serverSocket.close()
50
Java stream sockets ejemplo de aplicación
import java.io. import java.net. public
class BasicServer public static void
main(String args) throws IOException int
port 2345 if(args.length 1) port
Integer.parseInt(args0) BasicServer server
new BasicServer(port) server.launch()
private ServerSocket serverSocket private
BasicServer(int port) throws IOException
serverSocket new ServerSocket(port) pri
vate void launch() throws IOException
while(true) Socket connection
serverSocket.accept() BufferedReader br new
BufferedReader( new InputStreamReader(connect
ion.getInputStream())) String inputMessage
br.readLine() PrintWriter pw new
PrintWriter(connection.getOutputStream()) pw.p
rintln(inputMessage.toUpperCase()) pw.close()
//si no se cierra primero, hay que hacer
flush br.close() connection.close()

51
Java stream sockets ejemplo de aplicación
import java.io. import java.net. public class
BasicClient public static void main(String
args) throws Exception String remoteHost
"localhost" int remotePort
2345 BasicClient client new
BasicClient(remoteHost, remotePort) client.laun
ch() private String host private int
port private static final String message
"mensaje básico en iteración " private
BasicClient(String host, int port) throws
IOException this.host host this.port
port private void launch() throws Exception
for(int iteration 0 iteration lt 10
iteration) Socket connection new
Socket(host, port) PrintWriter pw new
PrintWriter(connection.getOutputStream()) pw.p
rintln(message iteration) pw.flush() Sys
tem.out.println("gtgtgtgtgt" message
iteration) BufferedReader br new
BufferedReader(new InputStreamReader(connecti
on.getInputStream())) System.out.println("ltltltlt
lt" br.readLine()) pw.close() br.close()
connection.close() Thread.sleep(1000)

52
Lección 2.4 Sockets UDP
2.1 Introducción 2.2 Streams en Java 2.3
Sockets TCP 2.4 Sockets UDP 2.5 Sockets con
entrada/salida asíncrona en Java
53
La API de sockets en modo datagama (UDP sockets)
  • La API de sockets en modo datagrama proporciona
    acceso al servicio de transporte de datos que
    implementa el protocolo UDP
  • El servicio UDP no es orientado a conexión ni
    proporciona entrega fiable de datos
  • El emisor envía un datagrama a un proceso remoto
    (dirección IP y puerto)
  • Si el datagrama no se pierde, eventualmente será
    recibido en el receptor
  • La API estándar de Java proporciona sockets
    orientados a datagrama que permiten utilizar
    directamente el servicio UPD que acabamos de
    describir
  • Un socket en modo datagrama proporciona un
    servicio full-duplex
  • Java también proporciona una abstracción
    adicional que provee de un servicio de transporte
    no fiable orientado a conexión basado en el
    protocolo UPD. Esta abstracción forma parte del
    runtime de Java y no supone modificación alguna
    sobre el funcionamiento del protocolo UDP
  • Todos los paquetes que pertenecen a una de estas
    conexiones lógicas comparten 4 parámetros (el
    runtime de Java asigna paquetes a conexiones
    usándolos) Puerto de origen, Dirección IP de
    origen, Puerto de destino, Dirección IP de
    destino
  • Vamos a estudiar en detalle el funcionamiento de
    los sockets UDP utilizando la funcionalidad
    proporcionada por la API estándar de Java

54
La clase DatagramSocket
  • La clase DatagramSocket forma parte del paquete
    java.net de la API estándar
  • Constructores
  • DatagramSocket() Crea un socket de datagrama y
    lo ata a un puerto libre en la máquina local.
    Este constructor suele crearse para desarrollar
    el extremo cliente de una aplicación.
  • DatagramSocket(int port) Crea un nuevo socket de
    datagrama y lo ata al puerto especificado en
    todas las interfaces de la máquina local. Este
    constructor suele utilizarse para desarrollar el
    extremos servidor de una aplicación
  • DatagramSocket(int port, InetAddress laddr) Crea
    un nuevo socket de datagrama y lo ata al puerto
    especificado en la dirección IP dada sobre la
    máquina local (para máquinas con varias
    interfaces). Este constructor suele utilizarse
    para crear el extremo servidor de una aplicación
  • DatagramSocket(SocketAddress bindaddr) Crea un
    nuevo socket de datagrama y lo ata a la dirección
    especificada (puerto y dirección IP). Este
    constructor suele utilizarse para crear el
    extremos servidor de una aplicación

55
La clase DatagramSocket
Algunos métodos void bind(SocketAddress addr)
Ata el socket de datagrama a la dirección
especificada (puerto y dirección IP) int
getLocalPort() Devuelve el puerto al que el
socket está atado void receive(DatagramPacket p)
Recibe un datagrama en el socket. Esta llamada es
bloqueante. Cuando este método retorna, los datos
se devuelven en el buffer del DatagramPacket. El
DatagramPacket también contiene la dirección IP y
el puerto del emisor. void send(DatagramPacket
p) Envía un datagrama desde el socket. El
DatagramPacket contiene los datos, su longitud,
la dirección IP del receptor y su número de
puerto void setTraffciClass(int tc) Permite
establecer es campo TOS (type-of-service) de los
paquetes IP que encapsulan los datagramas (RFC
1349) void close() Cierra el socket, no se
podrán volver a enviar ni a recibir datragamas
desde el socket
56
La clase DatagramPacket
  • La clase DatagramPacket forma parte del paquete
    java.net de la API estándar
  • Constructores
  • DatagramPacket(byte buf, int length) Construye
    un DatagamPacket para recibir datagramas con
    hasta length bytes de datos
  • DatagramPacket(byte buf, int length,
    InetAddress addr, int port) Crea un nuevo
    DatagramPacket para el envío de los datos
    especificados a la dirección y puerto remotos
    dados
  • DatagramPacket(byte buf, int offset, int
    length) Construye un DatagramPacket para la
    recepción de datos, que se depositarán con el
    offset especificado en el buffer dado
  • DatagramPacket(byte buf, int offset, int
    length, InetAddress addr, int port) Crea un
    DatagramPacket para enviar un datagrama UPD que
    contenga length bytes de datos a partir de
    bufoffset

57
La clase DatagramPacket
Algunos métodos InetAddress getAddress() Cuando
el DatagramPacket es para envío, indica la
dirección IP del receptor, cuando el
DatagramPacket es de recepción, indica la
dirección IP del emisor (siempre la dirección IP
del lado remoto) byte getData() Devuelve el
buffer de datos asociado a este DatagramPacket.
Si el DatagramPacket es de recepción, el buffer
contendrá los datos recibidos int getLength()
Devuelve en número de bytes útiles en el
datagrama. Este método permite determinar los
bytes de datos útiles que se pueden extraer del
buffer devuelto por getData() int getPort()
Cuando el DatagramPacket es para envío, indica el
puerto receptor, cuando el DatagramPacket es de
recepción, indica el puerto del emisor (siempre
el puerto del lado remoto) void setData(byte
buf) Permite asociar un nuevo buffer de datos
con el DatagramPacket. Si el DatagramPacket es de
recepción, los datos del datagrama recibido no
podrán exceder buf.length, en caso contrario, los
datos se truncarán void setLength(int length)
Indica el número de bytes útiles en el buffer
asociado al DatagramPacket. Este método es usado
cuando el DatagramPacket es de emisión para
indicar cuantos bytes del buffer especificado se
enviarán en el datagrama correspondiente void
setPort(int port) Indica el puerto asociado a
un DatagramPacket. Este método se usa para
indicar el puerto del receptor el datagramas de
envío
58
Sincronización de los DatagramSocket
Cliente
Servidor
server new DatagramSocket(2345)
client new DatagramSocket()
server.receive(datagramPacket)
client.send(datagramPacket)
Mensaje
client.receive(datagramPacket)
server.send(datagramPacket)
Mensaje
server.close()
client.close()
59
Sincronización de los DatagramSocket
Cliente
Servidor
server new DatagramSocket(2345)
client new DatagramSocket()
server.receive(datagramPacket)
client.send(datagramPacket)
Mensaje
client.receive(datagramPacket)
server.send(datagramPacket)
DatagramSocket server new DatagramSocket(2345)
La creación de un DatagramSocket atado a un
puerto es no -bloqueante
Mensaje
server.close()
client.close()
60
Sincronización de los DatagramSocket
Cliente
Servidor
server new DatagramSocket(2345)
client new DatagramSocket()
server.receive(datagramPacket)
client.send(datagramPacket)
Mensaje
client.receive(datagramPacket)
server.send(datagramPacket)
server.receive(datagramPacket) La llamada a
receive en un DatagramSocket es una
operación síncrona y, por tanto, bloqueante
Mensaje
server.close()
client.close()
61
Sincronización de los DatagramSocket
Cliente
Servidor
server new DatagramSocket(2345)
client new DatagramSocket()
server.receive(datagramPacket)
client.send(datagramPacket)
Mensaje
client.receive(datagramPacket)
server.send(datagramPacket)
Mensaje
client.send(datagramPacket) La llamada a send en
un DatagramSocket es una operación no-bloqueante,
el paquete se envía pero so se espera
ningún asentimiento
server.close()
client.close()
62
Sincronización de los DatagramSocket
Cliente
Servidor
server new DatagramSocket(2345)
client new DatagramSocket()
server.receive(datagramPacket)
client.send(datagramPacket)
Mensaje
client.receive(datagramPacket)
server.send(datagramPacket)
Mensaje
Cuando el mensaje se recibe, se desbloquea la
llamada al método receive de la clase
DatagramSocket
server.close()
client.close()
63
Sincronización de los DatagramSocket
Cliente
Servidor
server new DatagramSocket(2345)
client new DatagramSocket()
datagramSocket.close() Las llamadas al método
close son siempre no -bloqueante
server.receive(datagramPacket)
client.send(datagramPacket)
Mensaje
client.receive(datagramPacket)
server.send(datagramPacket)
Mensaje
server.close()
client.close()
64
Java Datagram Sockets ejemplo de aplicación
import java.io. import java.net. public
class BasicUDPServer public static void
main(String args) throws IOException
DatagramSocket udpSocket new
DatagramSocket(2345) DatagramPacket
datagramReceived new DatagramPacket(new
byte512, 512) while(true) udpSocket.recei
ve(datagramReceived) String messageReceived
new String(datagramReceived.getData(), 0
, datagramReceived.getLength()) byt
e answer messageReceived.toUpperCase().getByte
s() DatagramPacket datagramSent new
DatagramPacket( answer, answer.lengt
h, datagramReceived.getAddress(), data
gramReceived.getPort()) udpSocket.send(d
atagramSent)
65
Java Datagram Sockets ejemplo de aplicación
import java.net. public class BasicUDPClient
private final static String message "el
cliente envia el mensaje " public static void
main(String args) throws Exception
DatagramSocket udpSocket new
DatagramSocket() for(int i 0 ilt 10 i
) String messageSent message i
byte datos messageSent.getBytes() Dat
agramPacket datagram new DatagramPacket( d
atos, datos.length, InetAddress.getByN
ame("localhost"), 2345) udpSocket.send(d
atagram) System.out.println("gtgtgtgtgt"
messageSent) datagram new
DatagramPacket(new byte512, 512) udpSocket.r
eceive(datagram) String messageReceived new
String(datagram.getData(), 0, datagram.getLe
ngth()) System.out.println("ltltltltlt"
messageReceived) Thread.sleep(1000)
66
Java DatagramSockets orientados a conexión
  • La clase DatagramPacket proporciona una
    abstracción de envío de datagramas no fiable con
    orientación a conexión
  • Métodos implicados
  • void connect(InetAddress address, int port)
    Conecta el DatagramSocket a la dirección remota
    especificada. Una vez conectado, el socket sólo
    podrá enviar o recibir datagramas de la dirección
    remota especificada. Si se envía o recibe un
    datagrama con dirección IP o puerto remoto
    diferentes, se elevará una excepción
    IllegalArgumentException.
  • En algunos sistemas, si el socket remoto no
    existe en la dirección especificada, o si éste no
    se puede alcanzar, el DatagramSocket local
    recibirá un paquete ICMP (destination
    unreachable), lo que se notificará con una
    excepción PortUnreachableException en cualquier
    llamada a send() or receive()
  • void disconnect() Desconecta el DatagramSocket
  • boolean isConnected() Devuelve true si el socket
    está conectado, false en caso contrario

67
Lección 2.5 Sockets con entrada/salida asíncrona
en Java
2.1 Introducción 2.2 Streams en Java 2.3
Sockets TCP 2.4 Sockets UDP 2.5 Sockets con
entrada/salida asíncrona en Java
68
Operaciones bloqueantes en los sockets de Java
Socket UDP
Socket TCP
server new ServerSocket()
client new DatagramSocket()
server.accept()
client.send(datagramPacket)
Nuevo Socket conectado
read() sobre el Socket
client.receive(datagramPacket)
write() sobre el Socket
socket.close()
client.close()
serverSocket.close()
69
Problemas de las llamadas bloqueantes
  • Las llamadas bloqueantes facilitan la
    sincronización entre los procesos que comunican,
    pero complican algunos aspectos del desarrollo
  • En ciertas condiciones producen el bloqueo
    indefinido de un proceso
  • datagramSocket.receive(datagramPacket) pérdida
    del mensaje emitido
  • datagramSocket.receive(datagramPacket) crash
    del proceso emisor
  • serverSocket.accept() crash del proceso remoto
  • Pueden producir interbloqueo entre los procesos
    que comunican
  • Para procesos que deben mantener varias
    comunicaciones simultáneas, requieren el uso
    intensivo de hilos de ejecución (threads)
  • Los hilos limitan la escalabilidad del sistema
  • La gestión de muchos hilos hace menos eficiente
    el programa
  • Las llamadas bloqueantes dificultan la
    destrucción y reutilización de hilos

Proceso A
Proceso B
Proceso origen en espera de proceso destino
Proceso C
70
Uso de bloqueos con temporizador
  • Para evitar los bloqueos indefinidos y permitir
    que los procesos puedan reaccionar ante
    situaciones especiales, Java proporciona la
    posibilidad de establecer temporizadores
    asociados a las llamadas bloqueantes
  • Estos temporizadores funcionan del modo
    siguiente
  • El usuario elige un tiempo máximo (a través de
    una invocación)
  • Cuando se produce la invocación al método
    bloqueante, se inicia un temporizador
  • Si el método bloqueante retorna (es decir, se
    desbloquea) antes de que se alcance el tiempo
    máximo, el programa continúa con normalidad
  • Si se alcanza el tiempo máximo sin que la
    llamada retorne, se eleva una excepción desde
    dentro del método bloqueante
  • En todos los casos, el agotamiento del
    temporizador y el lanzamiento de la excepción
    correspondiente no afecta al estado del socket
    correspondiente
  • El desarrollador tiene la opción de manejar la
    excepción y dejar al programa continuar, o bien
    de tomar acciones adicionales que pueden incluir
    el cierre y destrucción del socket.

71
Estableciendo el tiempo de espera máximo
  • Estableciendo el tiempo máximo de espera en la
    clase ServerSocket
  • serverSocket.setSoTimeout(int tiemout)
  • tiemout especifica el tiempo máximo de espera en
    milisegundos. Un valor de 0 indica un tiempo de
    espera infinito
  • Afecta a las llamadas a serverSocket.accept(). Si
    el timeout se agota, se elevará una excepción
    java.net.SocketTimeoutException
  • Estableciendo el tiempo máximo de espera en la
    clase Socket
  • serverSocket.setSoTimeout(int tiemout)
  • tiemout especifica el tiempo máximo de espera en
    milisegundos. Un valor de 0 indica un tiempo de
    espera infinito
  • Afecta a las llamadas a read() en el InputStream
    asociado al socket. Si el timeout se agota, se
    elevará una java.net.SocketTimeoutException
  • Estableciendo el tiempo máximo de espera en la
    clase DatagramSocket
  • serverSocket.setSoTimeout(int tiemout)
  • tiemout especifica el tiempo máximo de espera en
    milisegundos. Un valor de 0 indica un tiempo de
    espera infinito
  • Afecta a las llamadas a datagramSocket.receive(p).
    Si el timeout se agota, se elevará una
    java.net.SocketTimeoutException

72
Ejemplo de desarrollo con temporizadores
  • Queremos que un proceso (o hilo) no se bloquee de
    manera indefinida
  • Usamos temporizadores para desbloquearlo de
    manera periódica
  • Cada cierto tiempo chequeamos si el necesario
    continuar con otra cosa

import java.net. import java.io. public
class TimeoutServerSocket public static void
main(String args) throws IOException
ServerSocket server new ServerSocket(2345)
server.setSoTimeout(250) //El valor del
timeout depende de la aplicación boolean
continuar true while(continuar) try
Socket connection server.accept() //Ha
cer cosas con la conexión //Podemos hacer
continuar false catch(SocketTimeoutExc
eption ste) //Chequear si debemos
continuar //Podemos elevar una
excepción //Podemos cerrar el socket y hacer
continuar false
73
Desarrollo con entrada/salida asíncrona
  • El modelo basado en temporizadores es una
    solución a medias
  • No evita el uso de múltiples hilos de ejecución
  • Si se quieren tiempos de respuesta bajos
    (timeouts pequeños) se degradan las prestaciones
  • Si se quieren prestaciones elevadas (timeouts
    grandes) se degradan los tiempos de respuesta
  • Muchos lenguajes de programación/entornos de
    desarrollo ofrecen operaciones de entrada salida
    asíncronas
  • Las operaciones de entrada/salida asíncronas
    ofrecen servicios de lectura y escritura no
    bloqueantes
  • La estrategia habitual para desarrollar programas
    con entrada/salida asíncrona se basa en el uso de
    modelos de programación orientados a eventos
  • El programa es un bucle a la espera de eventos
  • Cuando se producen eventos, el bucle realiza una
    iteración para procesarlos
  • Puede usarse un único hilo de ejecución o varios
    para procesar los eventos
  • Java define un conjunto de facilidades de
    entrada/salida asíncronas en el paquete java.nio
    (Java New Input Output) que existe desde el JDK
    1.4
  • Vamos a ver los fundamentos de estas facilidades,
    pero no profundizaremos

74
Java New Input Output
  • El paquete java.nio proporciona facilidades para
    el desarrollo de aplicaciones que requieran
    entrada/salida de alta velocidad y/o altas
    prestaciones
  • Delega algunas de las partes más tediosas
    (gestión de bufferes) al sistema nativo
  • El modelo de streams (definido en java.io) se
    basa en corrientes de bytes, el modelo de
    java.nio, se basa en bloques que se almacenan en
    bufferes
  • En java.nio existen dos conceptos (objetos)
    esenciales
  • Channel Es un objeto análogo a un stream, pero
    bidireccional (se puede leer y escribir sobre el
    mismo objeto) y que funciona sobre bloques y no
    sobre bytes
  • Buffer Es el objeto que se utiliza como
    contenedor de bloques para los channels
  • En java.nio todos los datos que se leen o
    escriben se gestionan a través de un objeto
    Buffer
  • Además de contener los datos, el objeto Buffer
    proporciona facilidades al programador que
    facilitan el desarrollo de aplicaciones
  • Existen diferentes tipos de buffers
    especialistas en diferentes tipos de datos

75
Bufferes en java.nio
  • La clase java.nio.Buffer es abstracta
  • Para cada tipo de datos primitivos existe una
    subclase especialista ByteBuffer, CharBuffer,
    ShortBuffer, IntBuffer, LongBuffer, FloatBuffer y
    DoubleBuffer
  • El Buffer contiene un bloque (array) de datos de
    entrada/salida que puede ser manipulado a través
    de métodos específicos
  • El funcionamiento de estos métodos se basa en
    tres variables de estado
  • La variable position
  • Especifica la siguiente posición del array que
    será escrita/leída
  • En cada operación de lectura/escritura, position
    se incrementa en una unidad
  • La variable limit
  • Especifica cuantas posiciones del array pueden
    ser leidas/escritas en total
  • Es decir, indica cuanto espacio tiene el array
    para lectura/escritura
  • Siempre se cumple que position lt limit
  • La variable capacity
  • Especifica la máxima cantidad de elementos que
    caben en el array
  • Es decir, indica el tamaño en memoria del array
    subyacente
  • Siempre se cumple que limit lt capacity

76
Bufferes en java.nio Ejemplo de uso
CharBuffer charBuffer CharBuffer.allocate(5) ch
arBuffer.put('a') charBuffer.put('b') charBuffer
.put('c') charBuffer.flip() char c
charBuffer.get() c charBuffer.get() c
charBuffer.get() c charBuffer.get()
77
Bufferes en java.nio Ejemplo de uso
CharBuffer charBuffer CharBuffer.allocate(5) ch
arBuffer.put('a') charBuffer.put('b') charBuffer
.put('c') charBuffer.flip() char c
charBuffer.get() c charBuffer.get() c
charBuffer.get() c charBuffer.get()
a
78
Bufferes en java.nio Ejemplo de uso
CharBuffer charBuffer CharBuffer.allocate(5) ch
arBuffer.put('a') charBuffer.put('b') charBuffer
.put('c') charBuffer.flip() char c
charBuffer.get() c charBuffer.get() c
charBuffer.get() c charBuffer.get()
a
b
79
Bufferes en java.nio Ejemplo de uso
CharBuffer charBuffer CharBuffer.allocate(5) ch
arBuffer.put('a') charBuffer.put('b') charBuffer
.put('c') charBuffer.flip() char c
charBuffer.get() c charBuffer.get() c
charBuffer.get() c charBuffer.get()
a
b
c
80
Bufferes en java.nio Ejemplo de uso
CharBuffer charBuffer CharBuffer.allocate(5) ch
arBuffer.put('a') charBuffer.put('b') charBuffer
.put('c') charBuffer.flip() char c
charBuffer.get() c charBuffer.get() c
charBuffer.get() c charBuffer.get()
a
b
c
81
Bufferes en java.nio Ejemplo de uso
CharBuffer charBuffer CharBuffer.allocate(5) ch
arBuffer.put('a') charBuffer.put('b') charBuffer
.put('c') charBuffer.flip() char c
charBuffer.get() c charBuffer.get() c
charBuffer.get() c charBuffer.get()
c a
a
b
c
82
Bufferes en java.nio Ejemplo de uso
CharBuffer charBuffer CharBuffer.allocate(5) ch
arBuffer.put('a') charBuffer.put('b') charBuffer
.put('c') charBuffer.flip() char c
charBuffer.get() c charBuffer.get() c
charBuffer.get() c charBuffer.get()
c b
a
b
c
83
Bufferes en java.nio Ejemplo de uso
CharBuffer charBuffer CharBuffer.allocate(5) ch
arBuffer.put('a') charBuffer.put('b') charBuffer
.put('c') charBuffer.flip() char c
charBuffer.get() c charBuffer.get() c
charBuffer.get() c charBuffer.get()
c c
a
b
c
84
Bufferes en java.nio Ejemplo de uso
CharBuffer charBuffer CharBuffer.allocate(5) ch
arBuffer.put('a') charBuffer.put('b') charBuffer
.put('c') charBuffer.flip() char c
charBuffer.get() c charBuffer.get() c
charBuffer.get() c charBuffer.get()
throws java.nio.BufferUnderflowException
a
b
c
85
Channels en java.nio
  • Channel es una interfaz definida en el paquete
    java.nio.channels
  • El Channel representa una conexión abierta hacia
    una entidad sobre la que se puede realizar
    entrada/salida de datos
  • Un Channel recién creado está abierto, una vez
    que se cierra no es posible realizar operaciones
    posteriores de entrada/salida. Se puede saber si
    un Channel está abierto invocando el método (de
    la interfaz) isOpen()
  • La interfaz Channel cuenta con un conjunto de
    subinterfaces y de clases que la implementan
  • Algunas Subinterfaces ByteChannel,
    InterruptibleChannel, ReadableByteChannel,
    WritableByteChannel, etc.
  • Algunas clases que lo implementan
  • FileChannel Especialista en asociarse a
    FileStreams para entrada/salida
  • SocketChannel Especialista en asociarse a
    instancias de la clase Socket
  • ServerSocketChannel Especialista en asociarse a
    instancias de ServerSocket
  • DatagramChannel Especialista en asociarse a
    instancias de DatagramSocket
  • SelectableChannel Channel que puede ser
    multiplexado a través de un Selector. Es
    superclase de todos los Channels que tienen que
    ver con Sockets

86
Ejemplo de uso de la clase FileChannel
import java.io. import java.nio. import
java.nio.channels. public class
FileChannelExample private static final String
FILENAME "channelFile.dat" private static
final String MESSAGE "hola nena" public
static void main(String args) throws
IOException writeFileWithChannel() readFile
WithChannel() public static void
writeFileWithChannel() throws IOException
FileOutputStream fos new FileOutputStream(FI
LENAME) ByteBuffer buffer ByteBuffer.allocate
Direct(1024) buffer.put(MESSAGE.getBytes("ISO-8
859-1")) buffer.flip() FileChannel ch
fos.getChannel() ch.write(buffer) ch.close()
public static void readFileWithChannel()
throws IOException FileInputStream fis new
FileInputStream(FILENAME) FileChannel ch
fis.getChannel() ByteBuffer buffer
ByteBuffer.allocateDirect(1024) ch.read(buffer)
buffer.flip() byte data new
bytebuffer.remaining() buffer.get(data) St
ring message new String(data,
"ISO-8859-1") ch.close()
87
Entrada/Salida asíncrona con Sockets en Java
  • Este mecanismo permite leer/escribir sobre un
    socket de red sin bloqueos
  • El modelo de programación se basa en eventos
  • Hay que registrar interés por un evento de
    entrada/salida determinado
  • Cuando el evento sucede, el sistema informa del
    mismo
  • Se procesa el evento ocurrido
  • Se vuelve a esperar por eventos
  • La clase Selector se utiliza para la gestión de
    eventos en subclases de SelectableChannels
  • Selector es una clase abstracta que proporciona
    un multiplexor de channels
  • Un SelectableChannel que se registra en un
    Selector, queda representado mediante un objeto
    de la clase SelectionKey
  • Las instancias de SelectionKey tienen múltiples
    métodos de interés
  • SelectableChannel channel() recupera el channel
    asociado a la key
  • Selector selector() recupera el Selector en que
    se creó la key
  • Al registrar el SelectableChannel hay que
    especificar los eventos de interés
  • Cuando todos los channels y sus eventos se han
    registrado, el Selector está listo

88
Uso de selectores
  • Partimos de instancias de subclases de
    SelectableChannel
  • Abrimos un Selector
  • Registramos los channels declarando los eventos
    de nuestro interés
  • Los eventos de interés son enteros potencias de
    dos
  • Se pueden activar varios eventos usando el
    operador (bitwise)
  • SelectionKey.OP_ACCEPT Cuando se ha recibido una
Write a Comment
User Comments (0)
About PowerShow.com