Está en la página 1de 9

DISEO DE UNA ARQUITECTURA CLIENTE/SERVIDOR MEDIANTE OBJETOS DISTRIBUIDOS EN JAVA

Jos Luis Pastrana Brincones (pastrana@lcc.uma.es) Dpto. Lenguajes y Ciencias de la Computacin. Universidad de Mlaga

Abstract El desarrollo de aplicaciones cliente/servidor usando sockets conlleva el diseo de un protocolo consistente en un lenguaje comn entre el cliente y el servidor. El diseo de dicho protocolo no siempre es sencillo y es una fuente de errores tales como el deadlock. En vez de trabajar directamente con sockets , las aplicaciones cliente/servidor, pueden ser desarrolladas mediante la invocacin de mtodos remotos en Java (JavaRMI). Java-RMI es un paquete que puede ser usado para el desarrollo de sistemas distribuidos. Dicho paquete le permite invocar mtodos de otra mquina virtual Java (posiblemente en otro host). El sistema RMI es muy similar (y generalmente ms fcil de usar) a la llamada a procedimientos remotos (RPC) que podemos encontrar en otros sistemas. En RMI el programador tiene la sensacin de realizar llamadas a mtodos locales de una clase local, mientras el sistema es el encargado de pasar los argumentos, ejecutar el mtodo y devolver los resultados de la mquina remota al objeto que ha realizado la llamada. Uno de los aspectos distintivos de RMI es su simplicidad. El conjunto de caractersticas soportadas por RMI son aquellas que hacen ms fcil el desarrollo de sistemas distribuidos: transparencia en la invocacin , recolector automtico de basura distribuido, acceso conveniente a Streams, etc. La invocacin remota es transparente ya que se realiza de idntica manera que la llamada aun mtodo local, y el recolector automtico de basura distribuido nos libera de la necesidad de preocuparnos por la liberacin de memoria de un objeto que ya no va a ser utilizado con independencia de que ste sea local o remoto.

Objetivos de Java-RMI Los objetivos del Java-RMI segn se definen en el manual de especificaciones son los siguientes: Soporte de invocacin de objetos remotos en diferentes mquinas virtuales Java. Soporte de retorno de resultados desde el servidor a los clientes. Integrar el modelo de objetos distribuidos en el lenguaje Java de una forma natural, mientras se mantiene la semntica de objetos ya definidas en Java. Realizar aplicaciones distribuidas lo ms simples y legibles posibles. Preservar la seguridad que provee el runtime system de Java.

RMI y el Modelo de Referencia OSI. El modelo de referencia OSI establece 7 niveles de para la comunicacin por red. En la siguiente figura se muestra cmo RMI puede ser descrito por dicho modelo.

Nivel de Aplicacin

Aplicacin de Usuario

cliente Nivel de Presentacin Stubs

servidor

skeletons

Nivel de Sesin Nivel de Referencias Remotas

Nivel de Transporte

TCP

Nivel de Red

IP

Nivel de Enlace de datos Interfaz Hardware

Nivel fsico

RED

La aplicacin del usuario est en el nivel superior y usa un esquema de representacin de datos para hacer transparente la comunicacin con los objetos remotos. El sistema RMI consiste en 3 etapas: El nivel Stub/Skeletons El nivel de Referencia Remota. El nivel de Transporte.

El nivel Stub/Skeletons es una interfaz entre una aplicacin y el resto del sistema RMI. Su propsito es transferir los datos al nivel de Referencia Remota. Aqu es dnde la serializacin de objetos entra en juego para permitir que los objetos Java sean transmitidos entre los espacios de direcciones. El nivel de Referencia Remota es responsable del manejo de la semntica de la invocacin, transmitir los datos al nivel de transporte usando una conexin orientada a Streams (TCP). El nivel de Transporte en la implementacin actual de RMI est basado en TCP, pero podra sustituirse por UDP. Finalmente, el nivel de Transporte es el responsable de establecer y manejar la conexin.

Desarrollo de Aplicaciones Cliente/Servidor en Java-RMI El desarrollo de aplicaciones cliente/servidor mediante Java-RMI requiere 6 etapas: 1. Definir una interfaz remota. 2. Implementar dicha interfaz remota. (Servidor). 3. Implementar la aplicacin que usa los objetos remotos. (Cliente). 4. Generar los Stubs (Proxies cliente) y Skeletons (entidades servidor). 5. Ejecutar el registry (servidor de nombres). 6. Ejecutar el servidor y los clientes.

Realizaremos un estudio de cada etapa con un ejemplo que nos ayudar a la mejor comprensin de cada una de ellas. Vamos a realizar un servidor de operaciones para matrices y vectores y un cliente que har uso de los servicios que ste nos proporciona.

Definicin de la Interfaz Remota.

El primer paso es definir una interfaz remota para los objetos remotos. Esto es necesario para que el usuario cliente conozca las operaciones que le son permitidas, as como los tipos, parmetros y clases que puede utilizar.

/* Archivo InterfazMatriz.java Interfaz del servidor remoto de Matrices public interface InterfazMatriz extends java.rmi.Remote { /* Operaciones para Vectores */ public int[] suma(int a[], int b[] ) throws java.rmi.RemoteException; public int[] resta(int a[], int b[] ) throws java.rmi.RemoteException;

*/

public int[] entero_por(int n, int a[] ) throws java.rmi.RemoteException; public int producto_escalar(int a[], int b[] ) throws java.rmi.RemoteException;

/* Operaciones para Matrices */ public int[][] suma(int a[][], int b[][] ) throws java.rmi.RemoteException; public int[][] resta(int a[][], int b[][] ) throws java.rmi.RemoteException; public int[][] entero_por(int n, int a[][] ) throws java.rmi.RemoteException; public int[][] producto(int a[][], int b[][] ) throws java.rmi.RemoteException; public int[][] inversa(int a[][] ) throws java.rmi.RemoteException; public int determinante(int a[][] ) throws java.rmi.RemoteException; }

Ntese que la interfaz debe declararse pblica para que los clientes puedan usarla, as como debe heredar de Remote para que el servidor se vea como un objeto remoto. tambin es obligatorio que todos los mtodos a implementar eleven la excepcin RemoteException, ya que esta se produce en determinados casos como fallos de conexin, o si cae el servidor, etc. Otro detalle que puede ser interesante es el uso del polimorfismo, se puede ver que hemos utilizado el mismo nombre de operador para las operaciones de vectores y matrices, pero la mquina Java sabr cul debe usar en funcin del tipo de sus parmetros. Ahora deberemos compilar nuestra interfaz, mediante: % javac InterfazMatriz.java Implementacin del Interfaz Remoto.

El siguiente paso en el ciclo de vida del desarrollo de software distribuido mediante Java-RMI es la implementacin del interfaz remoto.

/* Archivo ServerMatriz.java. Implementacin del Interfaz del servidor remoto */ import java.rmi.*; import java.rmi.server.UnicastRemoteObject; /* Nuestra clase hereda de UnicastRemoteObject porque va a ser creada /* para implementar un objeto remoto que usa el mecanismo por defecto /* de comunicacin de RMI. */ */ */

public class ServerMatriz extends UnicastRemoteObject implements InterfazMatriz { private String nombreServidor; public ServerMatriz ( String s ) throws RemoteException { nombreServidor = s; } /* Constructor de la clase. */ /* Operaciones para Vectores */ public int[] suma(int a[], int b[] ) throws RemoteException { int c[]; int i; if (a.length() != b.length()) return null; /* uso null como cdigo de error */ c = new int [a.length()] for(i=0;i<a.length(); ++i ) c[i] = a[i] + b[i]; return c; } ..................................... public static void main(String argv[]) { ServerMatriz servidor; System.setSecurityManager( new RMISecurityManager() ); /* Se crea e instala el manejador de seguridad para proteger /* al servidor de cdigos "maliciosos" desde el cliente. try { servidor = new ServerMatriz ( "ServidorMatriz" ); /* Objeto remoto */ */

Naming.rebind("//NombreMquina/ServidorMatriz",servidor); /* Registramos el objeto remoto */ System.out.println("ServidorMatriz instalado en NombreMquina"); } catch (Exception e) /* Cualquier tipo de excepcin */ { System.out.println("Se ha producido el siguiente error:"); System.out.println(e.getMessage()); e.printStackTrace(); } } }

Ahora deberemos compilar nuestra servidor, mediante: % javac ServerMatriz.java

Creacin de una aplicacin cliente que use el interfaz remoto. Vamos a realizar un sencillo ejemplo de un cliente que desea realizar la suma de dos vectores y para ello utilizar el servidor remoto. /* Archivo DemoMatriz.java */ import java.rmi.*; import java.net.*; public class DemoMatriz { public static void main(String argv[]) { int a[] = { 1, 2, 3, 4, 5 },b[] = { 6, 7, 8, 9, 0 }, i , resultado[] = new int[5]; InterfazMatriz servidorRemoto; try { String url = "//NombreMquina/ServidorMatriz"; /* Referenciamos el objeto remoto servidor */ ServidorRemoto = (InterfazMatriz)Naming.lookup(url); /* Realizamos la llamada al servidor */ resultado = ServidorRemoto.suma(a,b); /* Imprimimos los resultados */ System.out.print((); for(i=0;i<4;++i) System.out.print(a[i] + , ); System.out.print(a[4] + ) + ( );

for(i=0;i<4;++i) System.out.print(b[i] + , ); System.out.print(b[4] + ) = ( ); for(i=0;i<4;++i) System.out.print(c[i] + , ); System.out.println(c[4] + )); } catch (Exception e) /* Cualquier tipo de excepcin */ { System.out.println("Se ha producido el siguiente error:"); System.out.println(e.getMessage()); e.printStackTrace(); } } }

Ahora deberemos compilar nuestro cliente, mediante: % javac DemoMatriz.java

Generacin de Stubs y Skeletons. Ahora estamos preparados para generar los Stubs y Skeletons, para ello deberemos usar el compilador rmic. Un Stubs es un cliente proxy y un Skeletons es una entidad servidor que realiza las llamadas al objeto remoto servidor. Estos son cargados dinmicamente cuando son necesitados en tiempo de ejecucin. Para ello usaremos: % rmic ServerMatriz Esto generar los archivos ServerMatriz_Skel.class y ServerMatriz_Stub.class. Ntese que la variable de entorno CLASSPATH debe apuntar al directorio donde estn siendo compiladas y almacenadas las clases para que stas puedan ser localizadas. Un ejemplo tpico del valor de esta variable sera: setenv CLASSPATH .:/disk2/softw/jdk1.1.1/lib/classes.zip

RMI registry Antes de poder ejecutar nuestra aplicacin, debemos ejecutar el rmiregistry , que es un servidor de nombre que permite a los clientes obtener las referencias a los objetos remotos. Para ello ejecutaremos: % rmiregistry & El rmiregistry por defecto usa el puerto 1099, si por alguna razn estamos usando dicho puerto para otro cometido o deseamos utilizar otro puerto diferente, deberemos usar : % rmiregistry <puerto>&.

En este ltimo caso, deberemos indicar tambin el nmero del puerto en la llamada a Naming.Rebind y Naming.lookup aadiendo :<puerto< al nombre de la mquina.

Ejecucin del cliente y el servidor. Ahora ya estamos preparados para ejecutar el servidor en la mquina remota, para ello ejecutaremos: % Java ServerMatriz & Y obtendremos como resultado: ServidorMatriz instalado en NombreMquina Posteriormente en nuestra mquina local ejecutaremos el cliente: % Java DemoMatriz Y obtendremos como resultado:( 1, 2, 3, 4, 5 ) + ( 6, 7, 8, 9, 0 ) = ( 7, 9, 11, 13, 5 )

Serializacin de Objetos. Un tema importante a tener en cuenta es la serializacin de objetos. Debido a que tanto el paso de parmetros como el retorno de resultados se realiza va Streams, dichos parmetros deben ser serializables, es decir, que se puedan enviar como una tira de bytes. Para los tipos y clases standard en Java esto no es ningn problema, ya que son serializables, el problema viene dado cuando implementamos una clase propia que queremos que sea enviada como parmetro a un objeto remoto, o recibirla de ste. Para solucionar esto se debe importar en dicha clase el paquete java.io.Serializable y definir dicha clase como que implementa la interfaz Serializable.

Conclusiones. El desarrollo de aplicaciones cliente/servidor mediante sockets conlleva el diseo de un protocolo o lenguaje de comunicacin entre el cliente y el servidor que es fuente de gran cantidad de errores. Mediante el uso de RMI se consigue una transparencia en la comunicacin entre el cliente y el servidor, trantndose el servidor desde el punto de vista del cliente como si fuera un objeto local.

Referencias Remote Method Invocation System . Sun Microsystem Inc. Getting Started using RMI.Sun Microsystem Inc.

RMI and Object Serialization.Sun Microsystem Inc. Distributed Object Programming Using Java.Qusay H. Mahmond.

También podría gustarte