MENU
|
Ejemplo: RMI v/s TCP/IP
El siguiente ejemplo tiene como objeto ser una pequeña
introduccion a RMI, tratando un problema comun y corriente, de dos maneras distintas,
con una aplicacion cliente/servidor usando TCP/IP y con RMI.
El Problema
El problema consiste en calcular la suma de todos los numeros enteros desde 1 hasta un
numero pasado como parametro, para ello se utiliza una formula tribial. La tarea debe
ser realizada remotamente, por un servidor, que atenderá las consultas, realizará el
calculo, y luego devolverá la solucion. Además, debe tener un registro de todas
las operaciones realizadas, para responder inmediatamente, sin calcular, cuando se
realice una consulta repetida.
Cliente/Servidor
La idea de esta solucion es crear un servidor multihilos, como los vistos en clases,
que atienda las peticiones de multiples usuarios. A continuacion se muestra el
diagrama de clases de la solucion.
El funcionamiento a grandes rasgos es:
- El servidor parte y crea un objeto del tipo Tabla el cual se encargará
de guardar los calculos realizados.
- Luego queda escuchando conexiones en un determinado puerto
- Cuando llega una conexion, se crea un objeto Hilos, que implementa
la interface Runnable, se pasa la referencia al objeto Tabla y se echa
a correr el Thread.
- Luego se escucha la peticion del cliente, se busca en la tabla (por si ya fue
calculado)
- Se procesa (con un metodo de Tabla)
- Se guarda el resultado en un atributo de Tabla
- Finalmente, se devuelve la respuesta al cliente
Se utilizó la clase HashMap para guardar los resultados.
Como se puede ver no es mucho lo que difiere este programa de los ya vistos en clase.
CODIGOS:
Cliente.java
Servidor.java
Hilos.java
Tabla.java
DOCUMENTACION:
javadoc
RMI
Para se segunda solucion, se utilizó RMI (si no, no tendria gracia estar exponiendo).
La idea es utilizar las ventajas de RMI, para hacer que el servidor utilice su propia CPU
para utilizar los metodos implementados en la clase del objeto cliente.
A continuacion se presenta el diagrama de clases de la solucion RMI:
Como se explicó anteriormente, el cliente y el servidor jamas trabajan con las
implementaciones remotas, si no que, tienen que trabajar y comunicarse por medio
de interfaces. Se puede apreciar en el diagrama, que existen dos intefaces: Calculo
y Proceso. Asi como, MotorCalculo Hereda de Calculo, mientras que
calculoSumatoria hereda de Proceso.
El funcionamiento a grandes rasgos es:
- El servidor (MotorCalculo) se registra en RMIRegistry guardando su direccion.
- El cliente que necesite hacer un calculo, consulta al RMIRegistry, en busca del
objeto deseado. Si existe, le es devuelta una instancia de MotorCalculo.
- Luego crea un objeto: Proceso t = (Proceso) calculoSumatoria(int n);
- Con estas dos instancias, se ejecuta el metodo int ejecutarProceso(Proceso t)
de la clase MotorCalculo.
- El servidor recibe un objeto Proceso, que en realidad es una instancia de
calculoSumatoria y comienza a ejecutar los metodos de calculoSumatoria en el
servidor, pese a que es una clase en el cliente!!!
- Una vez que el calculo es realizado, el servidor devuelve un entero como resultado
del metodo ejecutarProceso(Proceso t).
Una de las ideas principales de rmi, es la de poder separar las fases de desarrollo,
en base a esto, nace la idea de dejar las clases de objetos remotos disponibles para
cada lado (servidor y/o cliente), a traves de un WebServer. La idea general se presenta
en el siguiente diagrama:
En la seccion de descargas se encuentran ambos programas comprimidos con un archivo de
texto que indica como compilar y ejecutar. El primer programa se ejecuta de manera normal,
mientras que para el segundo se deben seguir un par de pasos mas complejos. Estan todos
debidamente explicados en los leeme.txt correspondientes. A continuación se muestran los
pasos para compilar y ejecutar el código:
COMPILACION:
- En El Servidor
- Lo primero que se hace es compilar las interfaces, y crear un archivo
un archivo jar, para facilitar el traspaso de informacion.
cd /home/cvasquez/elo330/rmi/
javac src/calculo/Calculo.java
javac src/calculo/Proceso.java
jar cvf src.calculo.jar src/calculo/*.class
- Luego, se mueve el archivo jar recien creado hacia el servidor web,
para que pueda ser descargado por el/los cliente/s.
mv src.calculo.jar /pub/WWW/clases/
- Luego, cambia el classpath de java, para que reconosca el archivo
jar con la interfaces, y los archivos del servidor.
CLASSPATH=/home/cvasquez/elo330/rmi:/pub/WWW/clases/src.calculo.jar
- A continuacion se compila el servidor:
javac src/server/MotorCalculo.java
- Se crean los Stubs y Skeleton. En este caso, solo se genera un STUB
para el cliente, debido a que el servidor no lo necesita. Y se copia
al servidor web, para que el cliente pueda acceder a el.
rmic -d . src.server.MotorCalculo
mkdir /pub/WWW/clases/src
mkdir /pub/WWW/clases/src/server
cp src/server/MotorCalculo_*.class /pub/WWW/clases/src/server/
- Finalmente se extrae el archivo jar para que sea accedido por el
Cliente una vez ejecutado el programa.
cd /pub/WWW/clases/
jar xvf src.calculo.jar
- En El Cliente:
- Lo primero que se hace, es descargar el archivo jar: src.calculo.jar
del WebServer sel servidor, al WebServer del cliente.
- Luego se agrega al classpath, tanto el archivo recien descargado
como el path de trabajo.
CLASSPATH=/home/alm2000/cvasquez/elo330/rmi:
/home/alm2000/cvasquez/WWW/clases/src.calculo.jar
- Finalmente se compila el Cliente, y se deja la clase que utilizará
el servidor al WebServer.
cd /home/alm2000/cvasquez/elo330/rmi
javac src/cliente/testSumatoria.java
javac -d /home/alm2000/cvasquez/WWW/clases src/cliente/calculoSumatoria.java
EJECUCION
- En El Servidor
- Lo primero que hay que hacer es correr la aplicacion "policytool" de
JAVA, y crear las politicas de seguridad, y dejarlas en algun archivo en
el directorio del programa (tanto para el server como para el cliente):
grant
{
permission java.net.SocketPermission "*:1024-65535", "accept, connect, listen, resolve";
permission java.net.SocketPermission "*:80", "connect";
permission java.io.FilePermission "<>", "read";
};
- Luego hay que bajar el CLASSPATH con (UNIX):
CLASSPATH=
- A continuacion hay que abrir el registro RMI para poder registrar el servidor.
Se puede omitir el puerto, en cuyo caso, al puerto por omision sera el 1099.
rmiregistry [PUERTO]&
- Se actualiza el classpath para que encuentre los archivos del
servidor web.
CLASSPATH=/home/cvasquez/elo330/rmi:/pub/WWW/clases/src.calculo.jar
- Ahora, se puede levantar el servidor
java -Djava.rmi.server.codebase=http://200.1.27.172/clases/
-Djava.security.policy=java.policy
src.server.MotorCalculo 200.1.27.172 12345
- En el Cliente
- Realizar el mismo paso de la politica de seguridad realizada para el
servidor.
- En el cliente se actualiza el classpath.
CLASSPATH=/home/alm2000/cvasquez/elo330/rmi:
/home/alm2000/cvasquez/WWW/clases/src.calculo.jar
- Ahora hay que correr el programa cliente y listo. Esto se puede hacer
desde el directorio de este archivo, con la sentencia:
java -Djava.rmi.server.codebase=http://alumnos.elo.utfsm.cl/~cvasquez/clases/
-Djava.security.policy=java.policy
src.cliente.testSumatoria 200.1.27.172 12345 145
CODIGOS:
Proceso.java
Calculo.java
testSumatoria.java
calculoSumatoria.java
MotorCalculo.java
DOCUMENTACION:
javadoc
|