24
Programaci´ on Distribuida y su Aplicaci´ on Bajo Internet odulo 3.- Programaci´ on Concurrente y Prog. en red Curso 2001–2002. Juan S. Sendra ´ Indice 1. Programaci´ on Concurrente 1 1.1. Introducci´ on ............................ 2 1.2. Tareas en Java .......................... 3 1.3. Planificaci´ on ........................... 5 1.4. Sincronizaci´ on ........................... 6 1.4.1. Exclusi´ on m´ utua ..................... 7 1.4.2. Espera y Notificaci´ on .................. 8 1.5. Animaci´ on ............................. 9 2. Programaci´ on en Red 13 2.1. Contenido del paquete java.net ................. 13 2.2. Direcciones de Internet ...................... 13 2.3. Ports ................................ 15 2.4. Protocolos ............................. 16 2.5. URLs ............................... 16 2.6. Sockets .............................. 19 2.6.1. Lectura/Escritura de datos desde/a un socket ..... 21 1. Programaci´ on Concurrente Programaci´ on Concurrente es la denominaci´ on de las t´ ecnicas de progra- maci´on utilizadas para expresar paralelismo (varias actividades simult´ aneas) y resolver los problemas de comunicaci´ on y sincronizaci´ on que se presentan. Java es uno de los pocos lenguajes de programaci´ on que incorpora con- strucciones para expresar concurrencia 1 . 1 La programaci´ on concurrente resulta mucho m´ as simple y natural en Java que en otros lenguajes 1

Programaci on Distribuida y su Aplicaci on Bajo Internet

  • Upload
    others

  • View
    4

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Programaci on Distribuida y su Aplicaci on Bajo Internet

Programacion Distribuida y su Aplicacion Bajo

Internet

Modulo 3.- Programacion Concurrente y Prog. en red

Curso 2001–2002. Juan S. Sendra

Indice

1. Programacion Concurrente 11.1. Introduccion . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21.2. Tareas en Java . . . . . . . . . . . . . . . . . . . . . . . . . . 31.3. Planificacion . . . . . . . . . . . . . . . . . . . . . . . . . . . 51.4. Sincronizacion . . . . . . . . . . . . . . . . . . . . . . . . . . . 6

1.4.1. Exclusion mutua . . . . . . . . . . . . . . . . . . . . . 71.4.2. Espera y Notificacion . . . . . . . . . . . . . . . . . . 8

1.5. Animacion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9

2. Programacion en Red 132.1. Contenido del paquete java.net . . . . . . . . . . . . . . . . . 132.2. Direcciones de Internet . . . . . . . . . . . . . . . . . . . . . . 132.3. Ports . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152.4. Protocolos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162.5. URLs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162.6. Sockets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19

2.6.1. Lectura/Escritura de datos desde/a un socket . . . . . 21

1. Programacion Concurrente

Programacion Concurrente es la denominacion de las tecnicas de progra-macion utilizadas para expresar paralelismo (varias actividades simultaneas)y resolver los problemas de comunicacion y sincronizacion que se presentan.

Java es uno de los pocos lenguajes de programacion que incorpora con-strucciones para expresar concurrencia1.

1La programacion concurrente resulta mucho mas simple y natural en Java que en otroslenguajes

1

Page 2: Programaci on Distribuida y su Aplicaci on Bajo Internet

1 PROGRAMACION CONCURRENTE 1.1 Introduccion

1.1. Introduccion

La ejecucion secuencial (una actividad tras otra) presenta limitaciones adistintos niveles:

flexibilidad .- no podemos alterar la secuencia de ejecucion para dar pasoa tareas mas urgentes, o responder de inmediato a las acciones delusuario

interactividad .- la interaccion con el usuario debe seguir estrictamente elorden secuencial especificado por el programa

eficiencia .- Un sistema informatico dispone de diferentes recursos que po-tencialmente pueden explotarse en paralelo (ej.- podemos servir unapeticion a disco y simultaneamente utilizar el procesador, la tarjetade red, etc.). Si imponemos un orden secuencial podemos dilapidar esepotencial (ej.- si la aplicacion lanza una operacion sobre disco, duranteel periodo de lectura/escritura el procesador no puede ejecutar nuevasacciones

En la actualidad muchas aplicaciones necesitan concurrencia interna Ej.-un navegador web puede visualizar un documento mientras descarga otrosficheros. La concurrencia interna se implementa lanzando varas tareas quecooperan entre sı. Cada tarea mantiene un estado propio (codigo a ejecutar,pila, registro, punto de ejecucion) y ademas comparte con el resto los recursosdefinidos globalmente por la aplicacion.

Las distintas tareas se ejecutan teoricamente en paralelo. En la realidad,el numero de procesadores es inferior al de tareas, por lo que se utilizaunaestrategia de tiempo compartido, multiplexando el tiempo de procesadorentre las distintas tareas.

La programacion concurrente plantea ventajas e inconvenientes

2

Page 3: Programaci on Distribuida y su Aplicaci on Bajo Internet

1 PROGRAMACION CONCURRENTE 1.2 Tareas en Java

Ventajas Inconvenientes

Facilita la programacion reactiva .- al-gunos programas deben realizar ac-tividades como respuesta (reaccion) aestımulos externos. Ej.- un sistema detiempo real que controla un proce-so fısico debe responder a cambios entemperatura, humedad, iluminacion,etc.

Disponibilidad .- podemos replicar los ser-vicios o explotar el paralelismo paramejorar la disponibilidad (ej.- la im-presora es varios ordenes de magnitudmas lenta que un disco; cada escritu-ra en impresora se traduce en volcarlos datos a disco –tras lo cual la apli-cacion puede continuar– y lanzar unatarea que vuelca datos de disco a im-presora en cuanto esta esta libre

Simplifica el diseno .- Los objetos realessuelen mostrar comportamientoautonomo (cada uno evoluciona deforma independiente). Para represen-tarlos por programa es mucho masfacil lanzar una tarea para cada unode ellos. Ej.- para simular vehıculos,que poseen direccion, velocidad, etc.distintos entre sı

Paralelismo .- en sistemas multiprocesadorpodemos lanzar tareas independientesen cada procesador, y en sistemasmonoprocesador multiplexar el tiem-po de procesador para explotar el par-alelismo con otros dispositivos

Seguridad .- Ademas de comprobar que ca-da tarea es correcta, debemos garanti-zar que las tareas no interfieren entresı

Vivacidad .- Una o mas tareas pueden blo-quearse indefinidamente por distintascausas (ej.- otras actividades monop-olizan el uso de la CPU, o existe uninterbloqueo)

No determinismo .- La multiplexacion deltiempo de procesador no es fija, sinoque puede variar en cada ejecucion. Unprograma que depende del intercaladoconcreto de instrucciones resulta im-predecible (no determinista), compli-cando su depuracion

Coste .- Hay un coste extra por la mul-tiplexacion del tiempo de CPU (hayque decidir que tarea procede a con-tinuacion, y realizar el cambio de con-texto entre tareas), y un coste de sin-cronizacion (para evitar interferenciasentre tareas)

1.2. Tareas en Java

Podemos implementar tareas de dos formas:

Extender la clase java.lang.Thread. Posee los metodos para controlaruna tarea

start .- inicia la ejecucion de la tarea

run .- contiene el codigo a ejecutar

stop .- detiene la tarea

3

Page 4: Programaci on Distribuida y su Aplicaci on Bajo Internet

1 PROGRAMACION CONCURRENTE 1.2 Tareas en Java

otros .- metodos para suspender/relanzar la tarea, retrasar su ejecu-cion durante el periodo indicado, ceder el control a otras tareas,etc.

class ImprimeNum extends Thread {public void run() {

for (int i=-10; i<10; i++) System.out.print(""+i);}

}public class Test1 {

public static void main (String[] arg) {ImprimeNum in = new ImprimeNum();in.start();

}}

Utilizar el interfaz java.lang.Runnable. Lanzamos la tarea pasando alconstructor un objeto que implementa Runnable. Resulta util cuandoqueremos lanzar la tarea para un objeto que ya extiende a otra clase.

class ImprimeNum implements Runnable {public void run() {

for (int i=-10; i<10; i++) System.out.print(""+i);}

}public class Test1 {

public static void main (String[] arg) {Thread in = new Thread(new ImprimeNum());in.start();

}}

Una vez iniciada la ejecucion el procesador divide su tiempo entre lassentencias tras start() y el codigo de la tarea (en run). Cuando se alcanzael final del metodo run (o se invoca stop) la tarea ha finalizado.

El siguiente programa lanza tres tareas ImprimeNum. El orden en quese muestra la salida del programa depende del intercalado de instruccionesen la CPU, y por lo tanto es impredecible (puede variar al ejecutarse ensistemas diferentes, o incluso entre ejecuciones en un mismo sistema).

class ImprimeNum extends Thread {public void run() {

for (int i=-10; i<10; i++) System.out.print(""+i);}

}public class Test2 {

public static void main (String[] arg) {ImprimeNum in1 = new ImprimeNum();

4

Page 5: Programaci on Distribuida y su Aplicaci on Bajo Internet

1 PROGRAMACION CONCURRENTE 1.3 Planificacion

ImprimeNum in2 = new ImprimeNum();ImprimeNum in3 = new ImprimeNum();in1.start(); in2.start(); in3.start();

}}

Podemos dar nombre a las distintas tareas (ej.- para identificarlas du-rante la depuracion). El constructor de Thread admite como parametro unatira de caracteres que corresponde al nombre de la tarea.

Ej.- Incorporando nombre a las tareas, podemos distinguir el autor decada lınea en nuestro programa ejemplo

class ImprimeNum extends Thread {public ImprimeNum(String nom) {super(nom);}public void run() {

for (int i=-10; i<10; i++) System.out.print(getName()+": "+i);}

}public class Test3 {

public static void main (String[] arg) {ImprimeNum in1 = new ImprimeNum("Pepe");ImprimeNum in2 = new ImprimeNum("Carlos");ImprimeNum in3 = new ImprimeNum("Maria");in1.start(); in2.start(); in3.start();

}}

1.3. Planificacion

Una tarea es ejecutable (candidata a utilizar el procesador) si ha arran-cado (con start), no ha terminado todavıa (no ha finalizado el codigo de runni se ha ejecutado stop), y no esta esperando un recurso.

Las tareas ejecutables se situan en unas colas de planificacion organizadaspor prioridades y controladas por el soporte en ejecucion de Java.

Por defecto, cada nueva tarea tiene la misma prioridad que su creador

Podemos alterar la prioridad invocando Thread.setPriority con un ar-gumento entero en el rango [1..10] (mayor valor implica mayor priori-dad). La clase Thread define las constantes MAX PRIORITY, NORM PRIORITY,MAX PRIORITY

Cuando el procesador queda libre, se elige para ejecucion el proceso eje-cutable de mayor prioridad:

Si hay mas de uno con dicha prioridad, se elige uno de forma no de-terminista

Si se necesita ejecutar una tarea de mas prioridad que el que ocupa elprocesador, este es expulsado (pre-empted)

5

Page 6: Programaci on Distribuida y su Aplicaci on Bajo Internet

1 PROGRAMACION CONCURRENTE 1.4 Sincronizacion

El metodo yield devuelve voluntariamente el procesador

public class Test4 {public static void main (String[] arg) {

ImprimeNum in1 = new ImprimeNum("Pepe");ImprimeNum in2 = new ImprimeNum("Carlos");ImprimeNum in3 = new ImprimeNum("Maria");in1.setPriority(Thread.MIN_PRIORITY);in2.setPriority(Thread.NORM_PRIORITY);in3.setPriority(Thread.MAX_PRIORITY);in1.start(); in2.start(); in3.start();

}}

Los metodos de control (para afectar a la planifiacion) son los siguientes:

start .- Provoca que la tarea invoque su metodo run como una actividadindependiente. A menos que se invoque sobre la tarea un metodo es-pecial de control (ej. stop), la tarea termina cuando finaliza run

isAlive .- Es un metodo que devuelve cierto cuando la tarea ha arrancadopero todavıa no ha finalizado

stop .- Termina la tarea de forma irrevocable. Tras la terminacion puedeinvocarse de nuevo start para lanzar una nueva actividad usando lamisma tarea. La forma alternativa stop(excepcion) detiene la tarea ylanza la excepcion indicada.

suspend .- Suspende temporalmente la tarea, de forma que prosigue cuandootra tarea ejecuta resume sobre la tarea detenida.

sleep .- Suspende la tarea durante el numero de milisegundos especificado,y luego la reactiva de forma automatica

join .- Suspende al invocante hasta que se completa la tarea indicada (unsegundo argumento opcional indica un plazo maximo de espera enmilisegundos)

interrupt .- Provoca que se aborte la espera (iniciada con sleep, wait ojoin) lanzando una interrupcion tipo InterruptedException

1.4. Sincronizacion

En general las tareas deben cooperar entre sı, y para ello compartenobjetos (ej. una tarea modifica el estado de un objeto y otra tarea lee dichoestado). Nuestra responsabilidad es garantizar que las distintas tareas nointerfieren entre sı (ej. una tarea no debe cambiar los datos mientras otralos usa).

6

Page 7: Programaci on Distribuida y su Aplicaci on Bajo Internet

1 PROGRAMACION CONCURRENTE 1.4 Sincronizacion

Ej.- el siguiente codigo no protege contra posibles interferencias, y portanto no es determinista (dos tareas intentan modificar los campos del mismoobjeto, y el orden en que se modifican los datos depende del intercaladoconcreto).

public class Contador {int i=0;public void cuenta() {

int limite = i+100;while (i++ != limite) System.out.println(i);

}}public class TareaContador extends Thread {

Contador c;public static void main (String[] arg) {

Contador c = new Contador();TareaContador t1 = new TareaContador(c);TareaContador t2 = new TareaContador(c);t1.start(); t2.start();

}public TareaContador(Contador c0) {c = c0;}public void run() {c.cuenta();}

}

1.4.1. Exclusion mutua

Las interferencias entre tareas unicamente pueden aparecer en los frag-mentos de codigo que acceden a objetos compartidos (denominados seccionescrıticas). Para garantizar el determinismo (evitar interferencias) es suficientegarantizar la exclusion mutua entre secciones crıticas.

Con exclusion mutua garantizamos la ejecucion secuencial (no concur-rente) de las secciones crıticas → no pueden multiplexarse en el tiempoinstrucciones correspondientes a distintas secciones crıticas.

Java garantiza la exclusion mutua en el acceso a un metodo o bloque decodigo mediante la palabra synchronized

public class ContadorSincronizado extends Contador {public synchronized void void cuenta () {

int limite = i+100;while (i++ != limite) System.out.println(i);

}}

La palabra synchronized significa que dicho metodo es una seccion crıtica,o sea que debe ejecutarse en exclusion mutua con las restantes seccionescrıticas del objeto (si las tareas t1 y t2 invocan metodos sincronizados sobreel mismo objeto, una de las dos debe esperar).

Java garantiza que las operaciones primitivas (ej.- asignaciones sobretodos los tipos primitivos excepto long y double) son atomicas, y siempre

7

Page 8: Programaci on Distribuida y su Aplicaci on Bajo Internet

1 PROGRAMACION CONCURRENTE 1.4 Sincronizacion

pueden utilizarse con seguridad en contextos multitarea. Cualquier otro frag-mento de codigo que debe comportarse como atomico requiere la etiquetasynchronized.

La exclusion mutua se implementa mediante un contador interno de ca-da objeto Java. Dicho contador se incrementa cuando se invoca un metodosincronizado, y se decrementa cuando finaliza la ejecucion del mismo. Unmetodo no sincronizado puede ejecutarse con independencia del valor delcontador, pero los metodos sincronizados solo se pueden ejecutar si el conta-dor vale 0 (en caso contrario dicha tarea queda temporalmente suspendida).

Los metodos definidos en interfaces no pueden etiquetarse como sin-cronizados.

1.4.2. Espera y Notificacion

Ademas de evitar interferencias, las tareas deben comunicarse informa-cion utilizando objetos compartidos.

Algunos de los metodos definidos en un objeto solo deben invocarse endeterminados estados del objeto. ej.- en una lista podemos consultar la lon-gitud independientemente del estado de la lista, pero solo podemos extraersi la lista no esta vacıa.

Cuando una tarea invoca un metodo sobre un objeto compartido, y elestado del objeto no permite la ejecucion de ese metodo, dicha tarea debeesperar.

En general, la estructura de un metodo sincronizado es:

public synchronized tipoRetorno metodoEj (param) {while (no se puede ejecutar)

wait();.... // operaciones normalesif (el nuevo estado permite reactivar a otro)

notify():}

Los metodos de sincronizacion disponibles son:

wait .- suspende la tarea actual (se deposita en una cola interna asociada alobjeto) y libera la exclusion mutua sobre ese objeto. Existe un meto-do wait(ms), donde se especifica la espera maxima en milisegundos(transcurrido ese plazo, se reactiva de forma automatica)

notify .- reactiva a una (arbitrariamente) de las tareas de la cola asociadaal objeto

notifyAll .- igual que notify, pero liberando a todas las tareas suspendidassobre el objeto

8

Page 9: Programaci on Distribuida y su Aplicaci on Bajo Internet

1 PROGRAMACION CONCURRENTE 1.5 Animacion

Si durante la espera en la cola asociada al objeto ocurre una interrupcion(InterruptedException), se reactiva automaticamente la tarea (y se ejecutala correspondiente clausula catch).

Ej.- Implementamos una lista en las que distintas tareas pueden inser-tar/extraer de forma simultanea. Los metodos Inserta y Extrae son sin-cronizados, pero Longitud no. La lista posee un tamano maximo (indicadoen la creacion), se implementa mediante un vector circular, y solo permiteextraer si no esta vacıa e insertar si no esta llena.

public class Lista {int cabeza, cola, n, max;public Lista (int tallaMax) {

max=tallaMax;v = new Object[max]; // para guardar los datoscabeza=cola=n=0; // inicialmente vacia

}public int longitud() { return n; }public synchronized void inserta(Object x) {

while (n==max) // lista llenatry {wait();} catch(InterruptedException e) {return;}

v[cola]=x;cola = (cola+1) % max;n++;notifyAll(); // reactivamos por si alguien desea extraer

}public synchronized Object extrae() {

while (n==0) // lista vaciatry {wait();} catch(InterruptedException e) {return;}

Object x=v[cabeza];cabeza = (cabeza+1) % max;n--;notifyAll(); // reactivamos por si alguien desea insertarreturn x;

}}

1.5. Animacion

La animacion consiste en una sucesion rapida (y perfectamente sin-cronizada) de imagenes. Si deseamos realizar animaciones en un applet debe-mos:

1. Calcular la nueva imagen e invocar repaint para actualizar pantalla

2. Repetir el paso 1) de forma periodica (ej.- cada 50ms para obtener 20imagenes por segundo)

La siguiente discusion sobre animacion nos permitira ilustrar los mecan-ismos de programacion concurrente.

9

Page 10: Programaci on Distribuida y su Aplicaci on Bajo Internet

1 PROGRAMACION CONCURRENTE 1.5 Animacion

Ej1.- Animacion simple de una pelota (cırculo rojo) rebotando dentro deuna caja. La funcion paint se limita a dibujar la bola:

import java.awt.*;

public class BolaLoca extends java.applet.Applet implements Runnable {int x=30, y=40, r=20; // posicion y radio de la bolaint incx=2, incy=2: // direccion y magnitud del movimiento

public void init() {(new Thread(this)).start();}public void paint(Graphics g) {

g.setColor(Color.red);g.fillOval(x, y, r, r);

}}

public void run() {while (true) { // bucle infinito

int nx =x+incx;if (nx>=size().width || nx<0) incx*=-1; else x=nx;int ny =y+incy;if (ny>=size().heigth || ny<0) incy*=-1; else y=ny;repaint();

}}

}

Ej2.- Una animacion correcta requiere una base de tiempos. El Ej1 mues-tra una bola con velocidad erratica porque esta depende de la multiplexaciondel tiempo de procesador. Incorporamos la base de tiempos:

import java.awt.*;

public class BolaLoca extends java.applet.Applet implements Runnable {int x=30, y=40, r=20; // posicion y radio de la bolaint incx=2, incy=2: // direccion y magnitud del movimientoint retardo=50; // retardo de 50ms equivale a 20 fotogramas por segundo

public void init() {(new Thread(this)).start();}public void paint(Graphics g) {

g.setColor(Color.red);g.fillOval(x, y, r, r);

}}public void run() {

while (true) { // bucle infinitolong inicio = (new Date()).getTime();int nx =x+incx;if (nx>=size().width || nx<0) incx*=-1; else x=nx;int ny =y+incy;if (ny>=size().heigth || ny<0) incy*=-1; else y=ny;repaint();

10

Page 11: Programaci on Distribuida y su Aplicaci on Bajo Internet

1 PROGRAMACION CONCURRENTE 1.5 Animacion

try {Thread.currentThread.sleep(retardo-(new Date()).getTime()+inicio)

}catch (InterruptedException e) {}

}}

}

Ej3.- El ejemplo 2 muestra una velocidad constante, pero tambien apareceun notable efecto parpadeo debido a la falta de sincronizacion entre el mo-mento en que el sistema desea actualizar pantalla y el momento en que deseahacerlo el programa.

Para resolver el parpadeo debemos reducir al mınimo el intervalo de ac-tualizacion de pantalla. Existen dos vıas de solucion (utilizar un area declipping y utilizar doble buffering para pantalla), pero unicamente desarrol-lamos el esquema denominado doble buffering.

Se trata de componer el dibujo sobre una variable interna, y no sobrepantalla (posteriormente se vuelca esa variable a pantalla, un proceso muchomas rapido que dibujar cada elemento individual). A;adimos al applet elsiguiente codigo:

private Image im;private Dimension tallaim;private Graphics g2;

public final synchronized void update (Graphics g) {Dimension d=size();if (im==null || (d.width != tallaIm.width) || (d.heigth != tallaIm.heigth)) {

im = createImage(d.width, d.height);tallaIm = d;g2 = im.getGraphics();

}g2.clearRect(0,0,d.width,d.height);paint(g2);g.drawImage(im,0,0,null);

}

Ej4.- Anadimos la posibilidad de detener/reanudar la animacion medi-ante sendos clicks de raton

import java.awt.*;

public class BolaLoca extends java.applet.Applet implements Runnable {int x=30, y=40, r=20; // posicion y radio de la bolaint incx=2, incy=2: // direccion y magnitud del movimientoThread t; // tarea subyacenteboolean activo;

private Image im;

11

Page 12: Programaci on Distribuida y su Aplicaci on Bajo Internet

1 PROGRAMACION CONCURRENTE 1.5 Animacion

private Dimension tallaim;private Graphics g2;

public void init() {t=new Thread(this);activo=false;addMouseListener (new MouseAdapter() {

public void mousePressed(MouseEvent e) {if (activo) t.suspend(); else t.resume();activo = !activo;

}});

}

public void start() {t.start(); activo=true;}

public final synchronized void update (Graphics g) {Dimension d=size();

if (im==null || (d.width != tallaIm.width) || (d.heigth != tallaIm.heigth)) {im = createImage(d.width, d.height);tallaIm = d;g2 = im.getGraphics();

}g2.clearRect(0,0,d.width,d.height);paint(g2);g.drawImage(im,0,0,null);}

public void paint(Graphics g) {g.setColor(Color.red);g.fillOval(x, y, r, r);

}}

public void run() {while (true) { // bucle infinito

int nx =x+incx;if (nx>=size().width || nx<0) incx*=-1; else x=nx;int ny =y+incy;if (ny>=size().heigth || ny<0) incy*=-1; else y=ny;repaint();

}}

}

12

Page 13: Programaci on Distribuida y su Aplicaci on Bajo Internet

2 PROGRAMACION EN RED

2. Programacion en Red

Las caracterısticas de portabilidad, junto a las facilidades para accedera servicios basicos de red (URLs, sockets, etc.), justifican el desarrollo deprogramas Java disenados para ejecucion en red (ej. monitorizacion remotade equipos, aplicaciones de trabajo en grupo, etc.).

Este capıtulo introduce el soporte basico de red, y analiza la estructurade programas en red simples.

2.1. Contenido del paquete java.net

El paquete java.net contiene el soporte para programacion en red, orga-nizado como sigue:

Clases Interfaces Excepcionesgeneral ContentHandler ContentHandlerFactory BindException

InetAddress FileNameMap ConnectExceptionHttpURLConnection NoRouteToHostException

UnknownHostExceptionUnknownServiceException

Datagrama DatagramPacketDatagramSocketDatagramSocketImpl

Socket MulticastSocket SocketImplFactory URLStreamHandlerFactoryServerSocketSocketSocketImpl

URL URL URLStreamHandlerFactory MalformedURLExceptionURLConnectionURLEncoderURLStreamHandler

El resto del capıtulo introduce los distintos conceptos (IP, socket, URL,etc.) y detalla las definiciones asociadas con cada uno.

2.2. Direcciones de Internet

Cada ordenador conectado a Internet se identifica mediante una direc-cion unica de 4 bytes denominada direccion IP (normalmente se escribenlos cuatro valores separados por puntos: ej 199.3.45.234). Para simplificarsu uso, asociamos nombres a las direcciones IP (ej. ”www.hp.com”, ”mis-tral.dsic.upv.es”).

Un ordenador pueden disponer de varias direcciones IP (ej. porque disponede varias tarjetas de red), pero generalmente solo posee una. En cualquiercaso, la maquina posee un nombre simbolico unico.

Una direccion IP corresponde a la clase java.net.InetAddress

13

Page 14: Programaci on Distribuida y su Aplicaci on Bajo Internet

2 PROGRAMACION EN RED 2.2 Direcciones de Internet

Metodo Explicacion

InetAddress getByName(String host) throws

UnknownHostException

direccion IP del host

InetAddress[] getAllByName(String host)

throws UnknownHostException

todas las direcciones asociadas a esehost

InetAddress getLocalHost() throws

UnknownHostException

direccion IP de la maquina que eje-cuta el codigo

String getHostName() nombre correspondiente a lamaquina local

byte[] getAddress() direccion IP de esta maquina comovector de bytes (mayor peso en pos0)

int hashCode() devuelve un codigo hash para esa di-reccion

boolean equals(Object x) compara esta dir. con el objeto x

String toString() convierte la dir. en una tira imprim-ible

La clase InetAddress no posee constructores publicos. Para generar nuevosobjetos pasamos el nombre de la maquina (o una tira con su direccion fısica)al metodo de clase getByName.

try {InetAddress d1=InetAddress.getByName("mistral.dsic.upv.es");InetAddress d2=InetAddress.getByName("128.34.5.12");

}catch (UnknowHostException e) {

System.out.println(e.getMessage());}

Si la maquina posee varias direcciones utilizamos getAllByName

import java.net.*;class A {

public static void main (String[] arg) {try {

InetAddress[] d=InetAddress.getAllByName("www.apple.com");for (int i=0; i<d.length; i++)

System.out.println(d[i]);}catch (UnknowHostException e) {

System.out.println(e.getMessage());}

}}// muestra// www.applet.com/17.254.3.28// www.applet.com/17.254.3.37// www.applet.com/17.254.3.61// www.applet.com/17.254.3.21

El metodo InetAddress.getLocalHost() devuelve un objeto InetAddressque contiene la direccion del ordenador en el que se esta ejecutando el pro-grama.

14

Page 15: Programaci on Distribuida y su Aplicaci on Bajo Internet

2 PROGRAMACION EN RED 2.3 Ports

try {InetAddress yo=InetAddress.getLocalHost();

}catch (UnknowHostException e) {

System.out.println(e.getMessage());}

Dado un objeto InetAddress, podemos:

Obtener su nombre simbolico como String (getHostName)

Obtener su direccion IP como String (getHostAddress)

Obtener su direccion IP como vector de bytes (getAddress)

Averiguar si es o no una direccion multicast (isMulticastAddress)

El siguiente programa imprime informacion sobre la maquina local

import java.net.*;class A {

public static void main (String[] arg) {try {

InetAddress yo = InetAddress.getLocalHost();System.out.println("mi nombre es "+yo.getHostName()+

" y mi direccion es "+yo.getAddress());byte[] d = yo.getAddress();for (int i=0; i<d.length; i++) {

int unsignedByte = d[i] < 0 ? d[i]+256 : d[i];System.out.println(unsignedByte+" ");

}}catch (UnknowHostException e) {

System.out.println("No conozco ni mi direccion");}

}}

Tambien podemos averiguar el nombre de la maquina dada su direccionIP

2.3. Ports

En muchos casos hay que mantener abiertas varias conexiones simultaneascon maquinas distintas (ej. varias sesiones ftp, conexiones web, etc.). Coneste fin el interfaz de red se divide desde un punto de vista logico en 65536ports distintos.

El concepto de port es una abstraccion (no representa ningun compo-nente fısico). Cada paquete que circula por la red indica un numero de port

15

Page 16: Programaci on Distribuida y su Aplicaci on Bajo Internet

2 PROGRAMACION EN RED 2.4 Protocolos

ademas de la direccion IP destino; cuando la maquina destino recibe un pa-quete, utiliza el numero de port para determinar que programa utilizara elcontenido del mensaje (en un instante dado solo puede haber un programadado escuchando en cada port).

Cada port puede recibir varias conexiones simultaneas (ej. un servicioweb suele utilizar el port 80, y soporta varias conexiones simultaneas en dichoport). En resumen, a un port podemos asociar varias conexiones externassimultaneas, pero un solo proceso local.

Muchos servicios asumen numeros concretos de port (por convenio o porindicacion del protocolo). Ej.- los servidores http escuchan generalmente enel port 80, los servidores SMTP en el 25, los de Echo en el 7, etc. Otrosservicios no manejan ports predefinidos, sino que los descubren de formadinamica (ej. NFS).

2.4. Protocolos

Un protocolo define la forma en que se comunican dos maquinas. Ej

El protocolo Daytime (RFC 867) indica que el cliente se conecta alpuerto (port) 13 del servidor, tras lo cual el servidor contesta con unatira de caracteres que representa la hora actual y cierra la conexion

El protocolo Time (RFC 868) indica que el cliente se conecta al port9 del servidor, y entonces el servidor contesta con la hora actual enformato binario y cierra la conexion

Existen tantos tipos distintos de protocolos como de servicios que losutilizan. Los protocolos Lockstep requieren una respuesta en cada paso, pro-tocolos como FTP utilizan varias conexiones y permiten varias peticiones yrespuestas por conexion, protocolos como HTTP solo permiten una peticiony respuesta por conexion, etc.

2.5. URLs

Una URL (Uniform Resource Locator) es un mecanismo para identificarde forma no ambigua la ubicacion de un recurso en Internet. Una URL puededescomponerse hasta en 5 partes, que corresponden a:

protocolo .- JDK 1.1 entiende los protocolos mailto, ftp, file, http y ap-pletresource. Ademas define y utiliza internamente los protocolos doc,netdoc, systemresource, verbatim

maquina .- IP correspondiente a la maquina donde se localiza el servicio

port .- port a utilizar

fichero .-

16

Page 17: Programaci on Distribuida y su Aplicaci on Bajo Internet

2 PROGRAMACION EN RED 2.5 URLs

seccion .- referencia dentro del fichero

Ejemplos de URLs:

http://www.javasoft.comfile://Macintosh\%20HD/Java/docs/jdk%201.1/api/java.net.InetAddress.htmlmailto:[email protected]

La clase java.net.URL representa una URL. Hay constructores para crearURLs y metodos que descomponen una URL en sus elementos, pero la util-idad mas interesante es la posibilidad de obtener un stream (flujo de datos)de entrada a partir de una URL. de forma que podamos leer datos desde unservidor.

El objetivo es separar la gestion de los datos descargados, y la gestion delprotocolo utilizado para descargar los datos. El gestor de protocolo comunicacon el servidor y lleva a cabo cualquier negociacion previa con el mismo, ydevuelve como resultado el fichero o secuencia de bytes solicitados. Entoncesel gestor de contenido interpreta dicho fichero o secuencia de bytes y lostraduce en algun tipo de objeto Java (ej. InputStream o ImageProducer).

Cuando consumimos un objeto URL, Java busca un gestor adecuadopara el protocolo (si no hay ninguno, lanzala excepcion MalformedURLEx-ception). Podemos construir una URL a partir de una tira unica o de tirasseparadas para cada elemento de la URL (protocolo, maquina, port, fichero,seccion). Ademas, muchas paginas HTML contienen URLs relativas (ej. per-miten mantener un mismo documento en distintos mirrors sin invalidar lasreferencias internas), por lo que tambien existe un constructor para crearURLs relativas a una dada.

// URL(String U)try {

URL u = new URL("http:/www.poly.edu/schedule/fall97/bgrad.html#cs");}catch (MalformedURLException e) {}

// URL(String protocolo, String maquina, String fichero)try {

URL u = new URL("http","www.poly.edu","schedule/fall97/bgrad.html#cs");}catch (MalformedURLException e) {}

// URL(String protocolo, String maquina, int port, String fichero)try {

URL u = new URL("http","www.poly.edu",80,"schedule/fall97/bgrad.html#cs");}catch (MalformedURLException e) {}

// URL(String contexto, String u)try {

17

Page 18: Programaci on Distribuida y su Aplicaci on Bajo Internet

2 PROGRAMACION EN RED 2.5 URLs

URL u1 = new URL("http://sunsite.unc.edu/javafaq/course/week12/07.html);URL u2 = new URL(u1, "08.html");

}catch (MalformedURLException e) {}

La clase URL posee cinco metodos para dividir una URL en sus compo-nentes: getProtocol, getHost, getPort, getFile, getRef.

try {URL u = new URL("http:/www.poly.edu/schedule/fall97/bgrad.html#cs");System.out.println(

"\nEl protocolo es :"+u.getProtocol()+"\nLa maquina es :"+u.getHost()+"\nEl port es :"+u.getPort()+"\nEl fichero es :"+u.getFile()+"\nLa seccion es :"+u.getRef());

}catch (MalformedURLException e) {}

Si la URL no especifica un numero de Port, getPort devuelve -1 (lo cualindica que se utiliza el port por defecto para ese protocolo). Si la URL noespecifica un fichero, getFile devuelve /”.

Sobre una URL tambien podemos abrir una conexion que devuelve unflujo de entrada (InputStream).

Un flujo de entrada constituye una secuencia de bytes a los que podemosacceder mediante operaciones read y readBytes. Cuando se abre la conexion(operacion openStream) se descartan todos los campos de cabecera y controlprevios a los datos.

El siguiente ejemplo intenta la conexion con el servidor especificado,descarga los datos, y los escribe en pantalla.

import java.net.*;import java.io.*;

public class R6 { // lectura de datos desde una URLpublic static void main (String[] arg) {

try {URL u = new URL(arg[0]);InputStream is = u.openStream();DataInputStream dis = new DataInputStream(is);String linea;while ((linea=dis.readLine()) != null)

System.out.println(linea);}catch (MalformedURLException e) {System.out.println(e.Message());}catch (IOException e) {System.out.println(e.Message());}

}}

18

Page 19: Programaci on Distribuida y su Aplicaci on Bajo Internet

2 PROGRAMACION EN RED 2.6 Sockets

2.6. Sockets

En Internet enviamos datos entre maquinas utilizando TCP/IP. Losdatos se dividen en paquetes de talla variable, pero finita (ej < 64k) denom-inados datagramas. Si perdemos un paquete se retransmite solo el paqueteextraviado (en lugar de reenviar todos los paquetes), y si los paquetes llegandesordenados pueden reordenarse en el receptor.

Java permite manejar datagramas y Sockets. Un socket representa unacomunicacion fiable entre dos maquinas, ocultando al programador los de-talles de codificacion de paquetes, paquetes perdidos y retransmitidos, ypaquetes que llegan fuera de orden. El software de red de java gestiona deforma transparente la division de los datos en paquetes (en el emisor) y surecepcion y reconstruccion (en el receptor).

Las operaciones basicas que soporta un socket son la conexion a unamaquina remota (no puede conectarse simultaneamente a mas de una maquina),envıo de datos, recepcion de datos, y cierre de conexion.

La clase java.net.socket permite realizar todas las operaciones funda-mentales sobre sockets:

19

Page 20: Programaci on Distribuida y su Aplicaci on Bajo Internet

2 PROGRAMACION EN RED 2.6 Sockets

conexion mediante la construccion de nuevos sockets. Cada socket se aso-cia exactamente con una maquina remota (para conectar con otramaquina hay que crear otro socket).Como mınimo hay que especificar la maquina y port a los queconectamos (la maquina puede especificarse mediante una tira o unobjeto InetAddress, y el port debe ser un entero entre 1 y 65536).Tambien podemos especificar la maquina y el port desde el queconectamos (un valor 0 para el port indica la eleccion arbitraria deuno de los ports disponibles). Todos los constructores no solo creanel socket, sino que ademas intentan conectar el socket al servidorremoto (si no es posible, se activa una excepcion IOException).

public Socket (String host, int port)

throws UnknownHostException, IOException

public Socket (InetAddress dir, int port)

throws UnknownHostException, IOException

public Socket (String host, int port, InetAddress dirLocal, int portLocal)

throws UnknownHostException, IOException

public Socket (InetAddress dir, int port, InetAddress dirLocal, int portLocal)

throws UnknownHostException, IOException

envıo y recepcion Se realiza mediante streams (flujos) de entrada y salida. Existenmetodos para obtener flujos para entrada y para salida en un socket

public InputStream getInputStream () throws IOExceptionpublic OutputStream getOutputStream () throws IOException

cierre

public synchronized void close () throws IOException

fijar opciones

public void setTcpNoDelay (boolean on)

throws SocketException

public boolean getTcpNoDelay ()

throws SocketException

public void setSoLinger (boolean on, int val)

throws SocketException

public synchronized void setSoTimeout (int timeout)

throws SocketException

public synchronized int getSoTimeout ()

throws SocketException

public static synchronized void setSocketImplFactory (SocketImplFactory f)

throws SocketException

obtencion informacion

public InetAddress getInetAddress()public InetAddress getLocalAddress()public int getPort()public int getLocalPort()public String toString()

No podemos conectar con cualquier port en cualquier maquina: la maquina

20

Page 21: Programaci on Distribuida y su Aplicaci on Bajo Internet

2 PROGRAMACION EN RED 2.6 Sockets

remota debe estar esperando conexiones en ese port. El siguiente codigo per-mite averiguar que ports esperan conexiones en una maquina dada:

import java.net.*;import java.io.*;

public class R7 { // explora portspublic static void main (String[] arg) {

try {busca(InetAddress.getLocalHost());

}catch (UnknownHostException e) {

System.out.println("No conozco la maquina ");}

}

static void busca (InetAddress dir) {String host = dir.getHostName();for (int port=0; port<20; port++) {

try {Socket s = new Socket(dir,port);System.out.println("Hay un servidor escuchando en el port "+port);s.close();

}catch (IOException e) {

System.out.println("nadie escucha en el port "+port);}

}}

}

2.6.1. Lectura/Escritura de datos desde/a un socket

Una vez que hemos conectado un socket podemos enviar datos al servidora traves de un flujo de salida o leer datos mediante un flujo de entrada. Elsignificado exacto de los datos enviados/recibidos depende del protocoloutilizado.

El metodo getInputStream() devuelve un flujo de entrada (InputStream)que lee datos desde el socket.

import java.net.*;import java.io.*;import java.util.Date;

public class R8 { // lectura de datos desde un socketpublic static void main (String[] arg) {

try {Socket s = new Socket("sunsite.unc.edu",13);InputStream is = s.getInputStream();

21

Page 22: Programaci on Distribuida y su Aplicaci on Bajo Internet

2 PROGRAMACION EN RED 2.6 Sockets

DataInputStream dis = new DataInputStream(is);String hora = dis.readLine();System.out.println(hora);s.close();

}catch (UnknownHostException ex) {

System.out.println("No conozco la maquina ");System.out.println("hora local = "+(new Date()).toString());

}catch (IOException ex) {

System.out.println("Error de Entrada/Salida ");System.out.println("hora local = "+(new Date()).toString());

}}

}

El metodo getOutputStream() devuelve un flujo de salida (OutputStream)que escribe datos en el socket.

import java.net.*;import java.io.*;

public class whois {

public final static int port = 43;public final static String hostname = "whois.internic.net";

public static void main(String[] args) {

Socket theSocket;DataInputStream theWhoisStream;PrintStream ps;

try {theSocket = new Socket(hostname, port, true);ps = new PrintStream(theSocket.getOutputStream());for (int i = 0; i < args.length; i++) ps.print(args[i] + " ");ps.print("\r\n");theWhoisStream = new DataInputStream(theSocket.getInputStream());String s;while ((s = theWhoisStream.readLine()) != null) {System.out.println(s);

}}catch (IOException e) {System.err.println(e);

}

}

22

Page 23: Programaci on Distribuida y su Aplicaci on Bajo Internet

2 PROGRAMACION EN RED 2.6 Sockets

}

En la mayor parte de los casos el cliente desea intercalar lecturas y es-crituras. Algunos protocolos requieren una alternancia estricta entre lecturasy escrituras; otros, como HTTP, permiten varias operaciones de cada tipo(varias de lectura, varias de escritura), y otros protocolos permiten cualquiersecuencias de lecturas y escrituras. Java no impone ninguna restriccion (ej.una tarea puede leer de un socket mientras otra escribe en el mismo).

El siguiente ejemplo envıa una peticion a un servidor http utilizando unflujo de salida sobre un socket; luego, lee la respuesta mediante un flujo deentrada (el servidor cierra la conexion cuando ha enviado la respuesta)

import java.net.*;import java.io.*;

public class R10 { // lectura-escritura a un socket para HTTPpublic static void main (String[] arg) {

int port=80;for (int i=0; i<arg.length; i++) {

try {URL u=new URL(arg[i]);if (u.getPort() != -1) port=u.getPort();if (!(u.getProtocol().equalsIgnoreCase("http"))) {

System.out.println("Lo siento, pero no entiendo HTTP");continue;

}Socket s = new socket(u.getHost(), u.getPort());OutputStream os = s.getOutputStream();

PrintWriter pw = new PrintWriter(os, false); // no auto-flushing// a~nadimos las marcas al final de lineapw.print("GET" + u.getFile() + " HTTP/1.0\r\n");pw.print("Aceptamos: text/plain, text/html, text/*\r\n");pw.print("\r\n");pw.flush();

InputStream is = s.getInputStream();DataInputStream dis = new DataInputStream(is);String linea;while ((linea = dis.readLine()) != null) {

System.out.println(linea);}

}catch (MalformedURLException ex) {

System.out.println("No es una URL valida ");}catch (IOException ex) {

System.out.println(e.getMessage());}

23

Page 24: Programaci on Distribuida y su Aplicaci on Bajo Internet

2 PROGRAMACION EN RED 2.6 Sockets

}}

}

24