Objetivos Entender los elementos del trabajo con redes en Java. Implementar aplicaciones de red en Java. Aprender a implementar aplicaciones colaborativas basadas en redes. Construir un servidor multihilado.
Comunicación entre procesos Mecanismos de comunicación entre procesos [IPC: InterProcess Communication] Cuando en un sistema tenemos distintos procesos, necesitamos disponer de mecanismos que hagan posible la comunicación entre ellos. Se pueden utilizar distintos mecanismos de comunicación entre procesos: Pipes anónimos [Anonymous pipes] Permiten redireccionar la entrada o salida estándar de un proceso (utilizando | en la línea de comandos, por ejemplo). Sockets Usan la familia de protocolos TCP/IP (la que se utiliza en Internet). Su diseño original proviene del BSD UNIX [Berkeley Software Distribution]. Estándares de paso de mensajes MPI (Message Passing Interface, muy utilizado en clusters y supercomputadores) o PVM (Parallel Virtual Machina, otro estándar utilizado en multiprocesadores y multicomputadores).
Comunicaciones y multitarea Atributos y conexiones for ( ; ; ) { aceptar una petición crear una tarea } Servicio Acepta Mensajes mensaje Tarea manipuladora Tarea manipuladora Tarea manipuladora
Sockets Java proporciona un nivel de conexión basado en puertos y sockets. En su paquete java.net Un puerto es una abstracción de un lugar físico a través del que se puede establecer una conexión entre un cliente y un servidor. Se dice que el servidor proporciona el puerto y el cliente se enlaza al mismo. En general, en la arquitectura cliente-servidor existe un objeto activo servidor que proporciona un servicio y unos clientes que lo solicitan. Para conseguir establecer la comunicación entre ambos objetos existen sockets servidores y sockets de cliente representados por las clases SocketServer y Socket, situadas en el paquete java.net..
Esquema de comunicaciones basadas en sockets La comunicación bidireccional entre el cliente y el servidor se implementa en Java utilizando los flujos de entrada y salida (InputStream y OutputStream) Para cada socket se puede acceder a los flujos de entrada con getInputStream () y a los de salida con getOutputStream (). Cuando la conexión queda establecida, los dos sockets conectados pueden comunicarse entre sí mediante operaciones de lectura y escritura idénticas a las cualquier otro “stream” en Java (read y write). Hay que establecer un protocolo de comunicación entre el cliente y el servidor para poder interpretar esos mensajes.
La clase InetAddress Obtener un objeto InetAddress a través de un nombre de dominio static InetAddress getByName( String nombre) static InetAddress[] getAllByName( String nombre) Obtener un objeto InetAddress a través de una dirección IP static InetAddress getByAddress( byte[] dirIP) Obtener un objeto InetAddress que haga referencia a la máquina local static InetAddress getLocalHost() Obtener el nombre de dominio o la dirección IP de una máquina String getHostName() String getHostAddress() Convertir InetAddress a String String toString()
Sockets Stream (TCP, Transport Control Protocol) El protocolo TCP [Transmission Control Protocol] proporciona un conjunto de primitivas de servicio (operaciones básicas) con las que se pueden construir aplicaciones que requieran servicios orientados a conexión (aquéllas en las que primero se establece una conexión y luego se transmiten los datos). TCP también se encarga de reordenar los datos si éstos se reciben desordenados y de pedir automáticamente que se retransmitan los datos si se produce un error en la transmisión. Funcionamiento El cliente crea un Socket para solicitar una conexión con el servidor al que desea conectarse. Cuando el ServerSocket recibe la solicitud, crea un Socket en un puerto que no se esté usando y la conexión entre cliente y servidor queda establecida. Entonces, el SocketServer vuelve a quedarse escuchando para recibir nuevas peticiones de clientes.
Una aplicación sencilla con sockets TCP Servidor:
Tarea de servicio:
Cliente de Telnet: Cliente Java:
Sockets Datagrama (UDP, User Datagram Protocol) El protocolo UDP [User Datagram Protocol] proporciona servicios no orientados a conexión, no garantiza la entrega de los paquetes, ni su llegada en orden, ni la no existencia de duplicados. UDP se utiliza en algunas aplicaciones, como SNMP [ Simple Network Management Protocol ] o RTP [ Real-time Transport Protocol ] El tipo más sencillo de sockets, puesto que no es necesario establecer ninguna conexión para enviar y recibir datos. En Java, un objeto de tipo DatagramSocket representa un socket UDP y puede enviar o recibir datos directamente de otro socket UDP. Los datos se envían y reciben en paquetes autocontenidos denominados datagramas (igual que el correo convencional). Los datagramas se representan en Java mediante la clase DatagramPacket, que consiste simplemente en un array de bytes dirigido a una dirección IP y a un puerto UDP concretos. La clase MulticastSocket se puede emplear para enviar un mismo datagrama a muchos destinatarios simultáneamente.
Una aplicación sencilla con sockets UDP Receptor:
Emisor:
Sockets UDP multipunto Para unirse a un grupo multicast se debe crear primero un socket de tipo MulticastSocket en el puerto deseado e invocar después al método: joinGroup. Cuando un proceso envía un mensaje a un grupo multicast, recibirán el mensaje todos los procesos suscritos al grupo. Para recibir mensajes multicast es necesario pertenecer a un grupo, sin embargo, esto no es necesario para enviar mensajes al grupo. Un proceso puede abandonar el grupo mediante el método leaveGroup .
Una aplicación Multicast sencilla
La clase URL
RMI - Remote Method Invocation Internamente, RMI utiliza serialización de objetos para encargarse de la transmisión de datos a través de la red (de cara al programador, el acceso al objeto remoto es como una llamada a un método local). Para localizar un objeto al que se desee acceder, RMI proporciona un registro que se usa a modo de páginas amarillas. Como respuesta de las llamadas a métodos de un objeto remoto, RMI devuelve objetos y se encarga de obtener los bytecodes que sean necesarios (cuando se obtiene una referencia a un objeto cuyos bytecodes no están disponibles en la máquina virtual del receptor). El servidor crea algunos objetos y los hace accesibles a través del registro. A continuación, se queda esperando a recibir peticiones. El cliente obtiene una referencia a un objeto remoto (que está alojado en el servidor) y la utiliza para invocar métodos del objeto de forma remota.
Objetos e interfaces remotos Para que Servidor y Cliente se comuniquen, RMI proporciona un conjunto de mecanismos que facilitan las tareas del programador. El Stub Permite a los clientes invocar métodos de objetos remotos. Es una implementación parcial de los objetos remotos que permite: 1. Compilar los clientes sin disponer del código de los objetos remotos. 2. Abstraer al programador de los detalles de comunicación. Cuando la aplicación cliente invoca un objeto definido en el stub , el stub se encarga de hacer llegar la invocación a su destino.
La capa de referencia remota Se encarga de implementar un protocolo específico para la gestión de referencias remotas. Es totalmente independiente del stub y del skeleton Debe encargarse de: 1. Saber a qué corresponde una referencia determinada. 2. En el Cliente: Convertir las referencias locales empleadas por el stub en referencias remotas. 3. En el Servidor: Convertir las referencias remotas recibidas en el skeleton en referencias locales. 4. Comunicarse con la capa de transporte subyacente. El skeleton Permite a los servidores recibir invocaciones remotas a métodos implementados en objetos locales. Proporciona los argumentos necesarios para la ejecución de los métodos. Se encarga de devolver el resultado de la ejecución de un método. No hace falta implementarlo en Java 2. En esta versión el servidor habla directamente con la capa de referencia remota . Implementación Es necesario utilizar clases de tres paquetes diferentes: Java.rmi.* : Proporciona funcionalidad para la construcción de aplicaciones Cliente . Java.rmi.server.* : Proporciona funcionalidad para la construcción de aplicaciones Servidores . Java.rmi.registry.* : Proporciona funcionalidad para publicar y localizar un objeto remoto. Todos estos paquetes pertenecen al kit de desarrollo estándar de Java. Desarrollo de aplicaciones distribuidas con RMI Crear los distintos componentes de la aplicación, teniendo en cuenta que, para que a un objeto se pueda acceder de forma remota con RMI, es necesario que implemente una interfaz derivada de java.rmi.Remote. 2. Compilar con javac y generar los stubs con rmic. 3. Hacer accesibles los objetos remotos (usualmente, dejando los bytecodes correspondientes a los interfaces remotos y a los stubs en algún servidor web). 4. Arrancar la aplicación, que incluye el registro RMI, el servidor y el cliente.
Una aplicación sencilla con RMI Definir la interface de servicios remota: La interface Calculadora extiende a Remote y todos sus métodos pueden generar una excepción RemoteException
Implementar la interface remota: Implementar el servidor:
Implementar el cliente: Generar las clases, el Stub y arrancar el servidor de nombres: Compilar el paquete Generar el Stub y arrancar el servidor de nombres : Ejecutar la Clase ServidorCalculadora Ejecutar el Cliente
Práctica 16: Implementación de aplicaciones cliente/servidor con Java Objetivos Hacer uso de las clases del paquete java.net para la implementación de aplicaciones Cliente/Servidor Acceder remotamente a objetos en un entorno distribuido Ejercicios Tomando como referencia es ejercicio 2 de la pág 15-22 implementar una aplicación que permita listar via telnet los contactos de la agenda. Implemente una sala de chat usando Swing y RMI Complemente la sala de chat permitiendo el registro de usuarios cuyos datos son almacenados por Serialización. Tomando como referencia los casos de aplicación de: Gestión Académica y Empresa XYZ, liste e implemente los servicios que podría ofrecer en un entorno distribuido. Implemente una aplicación que controle remotamente el encendido y apagado del tanque del ejercicio 4 de la pág 12-19.