Distribución

Anuncio
Distribución en Java
Concurrencia y Distribución
Programación Avanzada
Posgrado en Ciencia e Ingenierı́a de la Computación, UNAM
1.
Introducción
TCP/IP es un conjunto de protocolos que permite a dos programas
comunicarse sobre un canal de comunicación, Esto se logra mediante crear
una conexión de datos entre los dos programas. Una vez establecida, la conexión es vista por los dos programas como un archivoal cual el emisor escribe
y el receptor lee. Un canal de comunicación bidireccional se estable mediante
permitir a los dos programas la lectura y escritura del archivo.
El proceso se ilustra en la Figura 1, donde un programa “cliente” establece contacto con un programa “servidor”, ambos ejecutándose en dos
computadoras diferentes. Mediante esta aproximación, es posible ennviar
transacciones a ser procesadas en otras máquinas.
Computadora
Servidor
Computadora
Cliente
Programa
Servidor
Programa
Cliente
Figura 1: Cliente y sevidor.
La siguiente tabla resume las responsabilidades de un cliente y un servidor:
1
Cliente
Servidor
2.
2.1.
Una aplicación o applet cliente envı́a transacciones a una
aplicación o applet servidor para su procesamiento.
Una aplicación o applet servidor procesa las transacciones
de parte de uno o más clientes.
Conceptos y términos
Nombres de máquina y localhost
Cada máquina conetada a Internet sae reconoce por una dirección IP
única. Esta es en realidad un número entero de 32 bits que se escribe en
forma de cuatro octetos de la forma 192.62.183.86. Sin embargo, como esto
es una forma muy poco amigable de nombrar computadoras, se utiliza en
lugar de esto un nombre simbólico de dominio.
Un ejemplo de nombre de dominio es hp.fciencias.unam.mx, y se lee
como la máquina hp está en el dominio fciencias, que se encuentra en
el dominio unam, del dominio mx. Los dominios de más alta jerarquı́a se
registran por acuerdo internacional, los niveles más balos por organizaciones
o por personas responsables de tal dominio. Utilizando esta estrategia cada
computadora del mundo tiene un único nombre de dominio que puede ser
relativamente fácil de recordar.
Por otro lado, en muchos sistemas de cómputo, el nombre de la computadora local tiene el “alias” de localhost. De tal modo, si se desea comunicarse con otra aplicación o applet que se ejecuta en la misma computadora,
entonces es posible utilizar el nombre localhost como el nombre de la
máquina. Esto permite probar programas que utilizan la red sin necesidad
de conectar la computadora a la red. Por supuesto, es necesario que el software de redes necesario debe estar instalado en la computadora para que
esto funcione.
2.2.
Puertos
Como puede haber muchos programas ejecutándose en una computadora
individual, se utiliza un número de puerto lógico como identificador único
del programa con que el usuario desea comunicarse. Un número de puerto
se representa por un número entero dentro del rango de 1 y 65536. Los
números de puerto entre 1 y 1024 se reservan para programas especı́ficos,
de modo que debe evitarse su uso. Por ejemplo, el conjunto de programas
FTP utilizan los puertos 20 y 21 para comunicar clientes y servidores FTP.
2
Utilizar uno de estos puertos puede cancelar el uso del cliente FTP de la
máquina local, ası́ como obtener resultados extraños cuando el programa se
comunica con otras máquinas. Desafortunadamente, algunos de los puertos
numerados fuera del rango 1 a 1024 también se utilizan por otros programas.
2.3.
Cliente
Un programa cliente es aquél que solicita al servidor realizar una tarea
de por su parte. El cliente inicia la conversación con el servidor. Un cliente
“ligero” realiza muy poca labor local, delegando la mayorı́a del trabajo al
servidor, mientras que un cliente “pesado” hace la mayor parte del trabajo
por sı́ mismo.
2.4.
Servidor
Un programa servidor es aquél que realiza tareas de parte de sus clientes.
El servidor puede comunicarse con el cliente para retornar resultados de su
solicitud.
2.5.
Socket
Un socket es un extremo o punto de conexiones para communicación
entre dos programas. En esencia, el socket es la conexión entre dos programas
desde el punto de vista del programador. La creación de un socket sucede
en dos casos principalmente:
Cuando un cliente se conecta a un socket como una conexión a un
puerto dado en una máquina dada.
Cuando un servidor se conecta a un socket que se conecta a un puerto
dado en la máquina anfitrión (host machine). Esta conexión resulta
incompleta, y se completará solamente cuando un cliente se conecte a
tal puerto.
2.6.
Resumen
La Figure 2 muestra cómo dos computadoras beta y gamma ejecutan
programas cliente (programas B y C) que se comunican con un programa
servidor (programa A) ejecutándose en el servidor alfa. Estas computadoras
se encuentran todas en el dominio fciencias.unam.mx.
3
beta.fciencias.unam.mx
alfa.fciencias.unam.mx
Programa B
S
Programa A
Servidor
S
Cliente
99
gamma.fciencias.unam.mx
S
Socket
99
Puerto
Programa C
S
Cliente
Figura 2: Dos clientes y un servidor.
Los dos programas cliente crean un socket local que conectan al puerto
99 en la máquina con el nombre de dominio alfa.fciencias.unam.mx. Esta
computadora ejecuta un programa servidor (programa A) que está constantemente “escuchando” el puerto 99, en espera de conexiones.
Algunos de los principales conceptos de distribución se resumen en la
siguiente tabla:
4
Dirección
IP
Nombre
de dominio
TCP
UDP
IP
Número
de puerto
Host
3.
Actualmente, un IPv4 (IP versión 4) usa un valor entero
de 32 bits para la dirección normalmente escrita como 4
bytes de la forma: 192.62.183.86. Nótese que el formato
de una dirección IP se expandirá a IPv6, permitiendo
direcciones de 128 bits, lo que permitirá un mayor número
de computadoras conectadas a Internet.
Nombre simbólico de una máquina o grupo de máquinas.
Cada dueño de un dominio puede registrar otros nombres
en ese dominio. Por ejemplo, la UNAM (unam.mx) puede
elegir los nombres de sus máquinas y otros sub-dominios en
su dominio. Cada dominio usualmente tiene un DNS (Domain
Name Server) que mapea el nombre de cada máquina en su
dominio a la dirección IP real. Un DNS es una computadora
que es capaz de proveer una dirección IP para un nombre de
dominio o solicitar a otro DNS que provea de esta información.
Transport Control Protocol. Un protocolo que garantiza que
cuando se establece y mantiene abierta una conexión, la
máquina receptora recibirá los mensajes que se le envı́an.
El mensaje se divide en paquetes, que recorren cualquier
ruta a su destino. Sin embargo, el protocolo TCP asegura el
re-ensamble de todos los paquetes individuales en el orden
correcto para entregarlo al receptor.
User Datagram Protocol. En este protocolo, el mensaje se
divide en paquetes y se envı́an al destino, pero no hay
ninguna garantı́a de que los paquetes llegarán en el order
correcto, o al menos llegarán.
Internet Protocol. Una colección de protocolos de los que
TCP y UDP son miembros.
Número en el rango de 1 a 65536. Ejemplos de números de
puerto utilizados son: 20 y 21, usados por FTP, 23, para
telnet, y 79, para finger.
La máquina o computadora en la que el programa se ejecuta.
La implementación
Desarrolle dos programas, uno cliente y uno servidor, para implementar un chatline simple, utilizando una interfaz gráfica de usuario (GUI).
Este programa permite a varias personas intercambiar mensajes atrvés de
Internet. Cada usuario del chatline ejecuta un programa cliente que envı́a
5
mensajes a un programa servidor central, y este re-envı́a estos mensajes a
todos los clientes. Este proceso se muestra en la Figura 3.
Cliente 1
Cliente 2
Servidor
El servidor re−envia a cada
cliente cualquier mensaje
que se le envie.
Cliente n
Los clientes mandan mensajes
al servidor, deslegando los
mensajes que el servidor les envia.
Figura 3: Un chatline.
Una ilustración de dos personas interactuando mediante el chatline se
muestra en la Figure 4.
3.1.
La clase Client
El cliente del chatline se compone de las siguientes clases:
Clase
Application
Client
TextArea
NetReader
NetWriter
TextField
Transaction
Resumen
Crea y maneja los componentes de comunicación.
Inicia al cliente.
El área de texto visual.
Lee información del servidor remoto.
Escribe información en el servidor remoto.
Componente visual.
Objeto que responde a una instancia de un TextField.
El diagrama de clases se muestra en la Figura 5.
La interfaz gráfica de usuario se implementa mediante crear la clase
Application como una subclase de la clase Frame, que contiene los objetos
6
Maquina mc0.local
Maquina mc1.local
mc0.local:2000(Mike)
started
Mike: Alguien por ahi?
cori: Si, yo...
mc1.local:2000(cori)
started
Mike: Alguien por ahi?
cori: Si, yo...
Alguien por ahi?
Si, yo...
Figura 4: Dos personas comunicándose mediate el puerto 2000.
Client
1
1
1
1
Application
1
1
1
1
1
NetReader
1
1
NetWriter
TextArea
1 1
Transaction
Figura 5: Diagrama de clases del cliente.
7
1
1
1
1
1
TextField
utilizados en la interfaz gráfica. De tal modo, el constructor de la clase
Application debe establecer dos ventanas:
Una ventana de salida, theOutput, intancia de la clase TextArea
Una ventana de entrada, theInput, instance de la clase TextField
La ventana de salida se utliza para desplegar las conversasiones que actualmente se llevan a cabo en el chatline, mientras que la ventana de entrada
se usa para que el usuaro local pueda contribuir a la conversación.
El ciclo principal de el proceso debe estar contenido en un método
start(), que permite leer los mensajes que se reciben del servidor, y desplegarlos en la ventana de salida. Esto sólo puede realizarse si se ha establecido
una conexión. Para ello, el nombre de la máquina, el puerto y el nombre
del usuario debe proveerse como parámetros de la lı́nea de comando, utilizando un método llamado params(). Este método debe implementarse de
modo que decodifique los parámetros de la lı́nea de comandos, y si encuentra
alguna inconsistencia, debe proveer un valor por defecto apropiado.
Otro método, setUpConnect(), debe implementarse para establecer la
conexión con la máquina servidor,, a través de un socket.
Finalmente, la clase Transaction implemlementa la acción en la ventana
de entrada, implementando la interfaz ActionListener. Esto requiere la
implementación del método actionPerformed(), que se ejecuta cada vez
que el usuario escribe un mensaje y presiona “enter”.
3.2.
La clase Server
El servidor lee los mensajes de texto de los clientes y los reenvı́a a todos
aquéllos que se encuentren actualmente conectados. El servidor del chatline
se compone, entonces, de las siguientes clases:
Clase
NetReader
NetWriter
Person
Server
TChatManager
TClientReader
Resumen
Lee información del servidor remoto.
Escribe información en el servidor remoto.
Crea un objecto activo que se comunica con el cliente.
Inicia el servidor.
Maneja la comunicación entre el cliente y el servidor.
Crea un objeto activo para leer información del cliente
y provee una interfaz para leer información.
8
En esencia, el servidor crea múltuiples instancias de la clase Person para
manejar a los usuarios individuales. Una instancia de la clase TChatManager
es un objecto activo que maneja el flujo de mensajes entre los usuarios
individuales. El diagrama de clases de la Figura 6 muestra la organización
del servidor.
1
TClientReader
1
1
*
Person
Server
1
1
1
1
*
NetReader
1
1
TChatManager
1
NetWriter
Figura 6: Diagrama de clases del servidor.
La clase Server debe implementar el ciclo principal de ejecución del
servidor chatline. En esencia, los usuarios hacen contacto con este servidor.
Por cada contacto, un objecto activo debe ser creado para controlar la comunicación con cada usuario. Además, un proceso por separado debe crearse
para “polear” cada usuario en turno para ver si han hecho contacto con el
servidor para enviar un mensaje, si lo han hecho, y entonces distribuirlo a
todos los usuarios.
3.3.
La clase TChatManager
La clase TChatManager debe implementarse para controlar las instancias
de la clase Person. Cada instancia de la clase Person es un objeto activo que
se mantiene mediante un arreglo theChatters, de tamaño MAXPERSONS. El
paper de una instancia de la clase Person es comunicarse con cada usuario
del chatline.
La clase TChatManager debe contar con un método add() que añada
un nuevo usuario a su colección de usuarios. Este debe ser un método sincronizado para prevenir la corrupción y/o mal uso de theChatters como
9
recurso conpartido. El arreglo theChatters debe permitir añadir y accesar
a differentes threads ejecutándose concurrentemente. Nótese que, en caso de
que ae haya alcanzado el número máximo de usuarios, un nuevo usuario
simplemente no puede conectarse.
Otro método de la clase TChatManager es remove(), que se encarga de
remover a un usuario inactivo de la colección de usuarios.
Varios otros métodos son necesarios para un funcionamiento adecuado:
el método getMessage() debe retornar un mensaje desde un usuario; si el
usuario no ha transmitido ningún mensaje, entonces debe retornar un valor
null. Este método es sincronizado, ya que cada usuario de la colección de
usuarios theChatters es un objeto activo que contı́nuamente monitorea la
lı́nea de comunicación entre sı́ mismo y su cliente.
Otro método getName() simplemente debe retornar el nombre del usuario. El métdodo putMessage() debe escribir un mensaje al usuario. El método sendToAll() envı́a un mensaje a todos los usuarios, incluyendo al emisor.
Finalmente, el método run() debe implementar la parte activa del objeto, que es un ciclo contı́nuo, poleando cada usuario por turno para ver si
ha enviado un mensaje de texto. Si ası́ es, entonces el mensaje de texto se
re-envı́a a todos los usuarios. Si el nombre del usuario no se conoce, entonces
el nombre que se envı́a como parte del mensaje de texto debe utilizarse como
el nombre del usuario.
Si el usuario ha salido del chatline, un mensaje EOF debe recibirse, en
cuyo caso los demás usuarios reciben un mensaje informando que tal usuario
ha salido de la sesión.
3.4.
La clase Person
La clase Person debe utilizarse para crear objetos activos que contı́nuamente monitorean la conexión de comunicación del cliente, buscando un
nuevo mensaje de texto. Esto se implementa como una funcionalidad de
una instancia de la clase TClientReader.
En esencia, la clase Person debe proveer de una interfaz limpia a los
objetos responsables de leer y escribir los canales de comunicación. Debe
contar con métdos para manipular lı́neas de texto: getLine(), putLine(),
setName() y getName().
10
3.5.
La clase TClientReader
La clase TClientReader debe crear un objeto activo que continuamente
monitoree la lı́nea de comunicación entre un usuario, esperando un mensaje
de texto para enviar. De tal modo, este proceso no debe bloquearse, para lo
que se utiliza un buffer unitario para almacenar el mensaje de texto recibido.
Se checa el buffer por un mensaje, en lugar de por una comunicación. De
tal modo, puede hacerse una solicitud no-bloqueable para ver si el buffer
contiene un mensaje. Como la espera de un mensaje de texto en el canal de
comunicaciones es una operación que si puede bloquearse, esta funcionalidad
debe llevarse a cabo por la parte activa del objeto. Ası́, el método run()
debe implementarse de modo que cuando se recibe un mensaje de texto, se
le coloque en el buffer. Recuerde que las operaciones sobre el buffer deben
ser sincronizadas, de modo que se prevenga la corrupción de datos.
La clase debe contar con un método storeIfSpace(), que almacene el
mensaje si hay espacio en el buffer. También, con un método getLine(), que
retorna el mensaje de texto almacenado en el buffer. Si no hay mensajes,
debe retornar un valor null.
3.6.
La clase NetReader
La clase NetReader debe simplificar laq lectura de datos desde el canal
de comunicación que se obtiene de un socket. La cadena EOF se da como
valor de retorno en el canal cuando un archivo termina o cuando se detecta
un error. La razón común de un error es que el canal ha sido cerrado del
otro lado, en cuyo caso retornar EOF resulta la acción apropiada. De tal
modo, esta clase cuenta con un método getLine() el cual lee una lı́nea de
caracteres del canal de comunicación, y cualquier error debe tratarse como
un fin de archivo. También, debe contar con un método close() que cierre
el canal de manera ordenada.
3.7.
La clase NetWriter
La clase NetWriter debe utilizarse para simplificar la escritura de datos
a un canal que se obtiene mediante un socket. El constructor de esta clase
toma como argumento al socket para crear un stream de salida. Requiere
contener el método putLine(), que escribe al canal de comunicación y el
método close(), que cierra en canal en la máquina remota.
11
Referencias
[1] Ken Arnold and James Gosling. The Java Programming Language.
Addison-Wesley, 1996.
[2] Barry Boone. Java Essentials for C and C++ Programmers. AddisonWesley, 1996.
[3] Distributed Processes: A Concurrent Programming Concept. In Communications of the ACM 21(11), 1978, pp. 934-941.
[4] Gary Cornell and Cay S. Horstsmann. Core Java. Prentice-Hall, 1996.
[5] David Flanagan. Java in a Nutshell. O’Reilly, 1996.
12
Descargar