You are on page 1of 27

7.

- CASO DE ESTUDIO RMI BÁSICO
Implementaremos una calculadora primitiva con la funcionalidad elemental que nos
permitirá sumar, restar, multiplicar y dividir dos operandos enteros. Su única
particularidad será que la podremos usar de forma remota en un entorno cliente-
servidor. El ordenador que contendrá el objeto que realizará los cálculos (la l!ica de las
operaciones" #ará funciones de servidor , mientras que el objeto que representa el
teclado y el visor de la calculadora (escribe los operandos y operador y muestra el
resultado" #ará funciones de cliente.
$ara llevar a cabo un cálculo se crearán dos procesos% proceso servidor y cliente. El
proceso cliente enviará al proceso servidor los operandos y el operador para llevar a
cabo el cálculo. El proceso servidor #ará el cálculo y devolverá el resultado al proceso
cliente que lo mostrará al usuario. &s' pues, el cliente no dispondrá de la l!ica de
cálculo de la calculadora pero podrá i!ualmente efectuar cálculos con ella.
(os dos procesos serán independientes el uno del otro y podrán correr en el mismo
ordenador o en ordenadores distintos donde e)ista una máquina virtual java y est*n
interconectados mediante una red +,$-I$ (#abitualmente, internet". Solamente es
necesario que el cliente conozca la direccin I$ (o nombre ./S" y puerto del ordenador
servidor. (os dos procesos tambi*n pueden correr en el mismo ordenador f'sico, como
dos procesos independientes dentro de la misma máquina. $ara ello se aprovec#a la pila
+,$-I$ que e)iste en todo ordenador que se precie y la posibilidad de tener varias
instancias de la 012, lo que permite simular una cone)in entre 2áquinas distintas. En
esta caso, la direccin I$ (local" y puerto tanto del servidor como del cliente son los
mismos.
(ue!o se describirá el desarrollo completo del servidor y el cliente en una aplicacin
t'pica 32I. $rimero se procede a desarrollar el servidor y despu*s el cliente para
disponer del objeto remoto antes de que pueda ser invocado.
7.1. DESARROLLAR EL OBJETO REMOTO
la parte servidora consistirá en tres partes%
• la interfaz remota, que definirá los m*todos que pueden ser invocados por el
cliente.
• (a implementacin de esta interfaz, que implementará cada uno de los m*todos
de la interfaz. &demás, puede implementar otros m*todos no remotos en caso de
ser necesarios para trabajar de forma local en el lado del servidor.
• El servidor propiamente dic#o, que llevará a cabo las tareas de administracin y
ejecucin del servidor% instalar un controlador de se!uridad, instanciar el objeto
remoto a partir de la interfaz y su implementacin, situar el objeto remoto en el
re!istro para #acerlo visible a los clientes, y arrancar la parte servidora #aciendo
posible que los clientes invoquen m*todos remotos.
7.1.1 LA INTERFAZ REMOTA: DEFINICIÓN DEL OBJETO REMOTO
/o es posible acceder a los objetos remotos directamente, slo son accesibles a trav*s
de su interfaz. Esta interfaz deberá e)tender la clase 3emote para identificar el objeto
como remoto y contener la firma de todos los m*todos remotos los cuales por
requerimiento deben lanzar la e)cepcin 3emoteE)ception en su cláusula t#ro4s.
+endremos tantas interfaces como objetos remotos e)istan en nuestra aplicacin. ,ada
interfaz se tratará en un fic#ero de cdi!o aparte, como es l!ico. En este ejemplo slo
e)iste un objeto remoto y, por lo tanto, una sola interfaz. Esta interfaz está contenida en
el fic#ero ,alculadora.java con el si!uiente cdi!o, donde vemos cmo se declaran la
firma de los cuatro m*todos remotos que se corresponden con las cuatro operaciones
que efectúa nuestra calculadora remota%
5 public interface ,alculadora e)tend' java.rmi.3emote 6
7
8 public lon! sumar (lon! a, lon! b" t#ro4s java.rmi.3emoteE)ception9
: public lon! restar (lon! a, lon! b" t#ro4s java.rmi.3emoteE)ception9
; public lon! multiplicar(lon! a, lon! b" t#ro4s java.rmi.3emoteE)ception9
< public lon! divider (lon! a, lon! b" t#ro4s java.rmi.3emoteE)ception9
= >
?
7.1.2 LA IMPLEMENTACIÓN DE LA INTERFAZ: IMPLEMENTAR EL
OBJETO REMOTO
para la implementacin de la interfaz, crearemos la clase ,alculadoraImpl. El sufijo
Impl se usa como convenio para indicar que se trata de la clase que implementa un
objeto remoto, aunque el nombre de esta clase es totalmente libre. Esta clase debe
e)tender la clase @nicast3emoteAbject otor!ándole capacidades para manejar la mayor
parte de las tareas asociadas con la creacin de un servidor 32I. +ambi*n como es
l!ico, debe implementar la interfaz remota, en este caso la intarfaz ,alculadora.
En el si!uiente cdi!o (fic#ero ,alculadoraImpl.java" pdemos ver la implementacin de
los m*todos que definen la aritm*tica de las operaciones de la calculadora%
5 public class ,alculadoraImpl e)tend' java.rmi.server. @nicast3emoteAbject
7 implements ,alculadora 6
8 --,onstructor
: public ,alculadoraImpl(" t#ro4s java.rmi.3emoteE)ception6
; super ("9
< >
=
? public lon! sumar (lon! a, lon! b" t#ro4s java.rmi.3emoteE)ception 6
B retunr aCb9
5D >
55
57 public lon! restar (lon! a, lon! b" t#ro4s java.rmi.3emoteE)ception 6
58 return a-b9
5: >
5;
5< public lon! multiplicar (lon! a, lon! b" t#ro4s java.rmi.3emoteE)ception 6
5= return a E b9
5? >
5B
7D public lon! divider (lon! a, lon! b" t#ro4s java.rmi.3emoteE)ception 6
75 return a - b9
77 >
78
7: >
7.1.3 LA CLASE SERVIDORA
$ara terminar con la parte servidora, crearemos el servidor propiamente dic#o, que
llevará a cabo las si!uientes tareas%
Establecer un controlador de se!uridad. En esta caso, es un objeto de la clase
32ISecurity2ana!er. Este controlador satisface el requisito que impone 32I para
descar!ar los objetos al cliente que son pasados como parámetros durante la invocacin
de m*todos al servidor. $or razones de estricta se!uridad, a partir de la versin 5.7 de
java, es necesario además confi!urar la pol'tica de se!uridad del sistema e)pl'citamente.
,rear el objeto remoto ,alculadora a partir de la clase que la implementa%
,alculadora c F ne4 ,alculadoraImpl ("9
Se asi!na n nombre identificador al objeto remoto que servirá para que los clientes
encuentren este objeto remoto en el momento de la invocacin. El servidor asi!na el
identificador Servicio,alculadora al objeto remoto ,alculadora y lo re!istra en el
servicio de nombres del sistema que en nuestro caso es el 32I3e!istry. .e esta forma,
los clientes podrán localizar en el re!istro el objeto remoto ,alculadora a partir de su
identificador. $ara efectuar el re!istro es necesario especificar la @3( de 32I3e!istry,
que al encontrarse en la misma máquina la direccin será rmi%--local#ost%5DBB (local#ost
indica la direccin por defecto del propio "
RMI AVANZADO...............................................................................................................................................
CALLBACK DE CLIENTE................................................................................................................................
I/,3E2E/+A .E (& $&3+E ,(IE/+E $&3& ,&((G&,H .E ,(IE/+E..................................................................
I/,3E2E/+A .E (& $&3+E SE31I.A3& $&3& ,&((G&,H .E ,(IE/+E.............................................................
$&SAS $&3& ,A/S+3@I3 @/& &$(I,&,II/ 32I ,A/ ,&((G&,H .E ,(IE/+E................................................
STUB DOWNLOADING....................................................................................................................................
EL GESTOR DE SEGURIDAD DE RMI........................................................................................................
I/S+&/,I&,II/ .E @/ JES+A3 .E SEJ@3I.&. E/ @/ $3AJ3&2& 32I........................................................
(& SI/+&KIS .E @/ LI,ME3A .E $A(N+I,&S .E SEJ@3I.&. .E 0&1&..............................................................
@+I(IO&/.A S+@G .AP/(A&.I/J Q @/ LI,ME3A .E $A(N+I,&S .E SEJ@3I.&..........................................
&(JA3I+2AS $&3& ,A/S+3@I3 @/& &$(I,&,II/ 32I, R@E $E32I+& S+@G .AP/(A&.I/J.......................
RESUMEN........................................................................................................................................................
EJERCICIOS....................................................................................................................................................
REFERENCIAS...............................................................................................................................................
RMI avanzado
En el último capítulo, Java RMI se describió como ejemplo de un sistema de
objetos distribuidos. En dicho capítulo sólo se mostraron las características de
diseño más básicas de RMI, aunue se mencionó ue el !"I poseía un
e#tenso conjunto de características. El lector puede i$norar este capítulo si no
está interesado en e#plorar de %orma más detallada RMI. &in embar$o, es mu'
recomendable el uso de los $estores de se$uridad (v)ase sección *.+, en
todas las aplicaciones RMI.
Este capítulo anali-ará al$unas de las características avan-adas de RMI más
interesantes, a saber, ./descar$a01 stub downloading, gestores de
seguridad, ' callback de cliente. !unue no se trata de características
inherentes del paradi$ma de objetos distribuidos, se trata de mecanismos ue
pueden ser útiles para los desarrolladores de aplicaciones. !dicionalmente, el
estudio de estos temas permite al lector re%or-ar su conocimiento del
paradi$ma de objetos distribuidos en $eneral, ' del !"I de RMI en particular.
Callback de cliente
,onsid*rese una aplicacin 32I donde un objeto servidor debe notificar a los procesos
participantes la ocurrencia de al!ún evento. ,omo ejemplos, en un chat, cuando un
nuevo participante entra, se avisa al resto de los participantes de este #ec#o9 en un
sistema de subastas en tiempo real, cuando empiezan las ofertas, se debe avisar a los
procesos participantes. Esta caracter'stica tambi*n es útil en un jue!o en red cuando se
informa a los ju!adores de la actualizacin del estado del jue!o. .entro del entorno del
&$I básica de 32I presentada en el cap'tulo anterior, es imposible que el servidor inicie
una llamada al cliente para transmitirle al!una clase de informacin que est* disponible,
debido a que una llamada a m*todo remoto es unidireccional (del cliente al servidor".
@na forma de llevar a cabo la transmisin de informacin es que cada proceso cliente
realice un s!"# al objeto servidor, invocando de forma repetida un m*todo remoto,
que supn!ase que se llama haComenzadoOferta, #asta que el m*todo devuelva el valor
booleano verdadero%
InterfazServidor # F
(InterfazServidor" /amin!.looSup(@3(3e!istro"9
4#ile (T(#.#a,omenzadoAferta("" 69>
-- comienza la oferta
El s!"# (polling" es de #ec#o una t*cnica empleada en muc#os pro!ramas de red.
$ero se trata de una t*cnica muy costosa en t*rminos de recursos del sistema, ya que
cada invocacin a un m*todo remoto implica un thread separado en la máquina
servidora, además de los recursos de sistema que su ejecucin conlleva. @na t*cnica
más eficiente se denomina callback% permite que cada objeto cliente interesado en la
ocurrencia de un evento se re!istre a s' mismo con el objeto servidor, de forma que el
servidor inicie una invocacin a un m*todo remoto del objeto cliente cuando dic#o
evento ocurra. (a Li!ura ?.5 compara las dos t*cnicas% sondeo y callback.
En 32I, el callback "# $%&#!'# es una caracter'stica que permite a un objeto cliente
re!istrarse a s' mismo con un objeto servidor remoto para callbacks, de forma que el
servidor pueda llevar a cabo un invocacin al m*todo del cliente cuando el evento
ocurra. May que observar que con los callbacks de clientes, las invocaciones de los
m*todos remotos se convierten en bidireccionales, o dúplex, desde el cliente al servidor
y viceversa. .ebido a que el &$I de 32I básica, introducida en el cap'tulo anterior, slo
permite invocacin de m*todos remotos de clientes en objetos servidores, se necesita
claramente sinta)is adicional para dar soporte a esta nueva caracter'stica.
,uando un objeto servidor realiza un callback, los papeles de los dos procesos se
invierten% el objeto servidor se convierte en cliente del objeto cliente, debido a que el
primero inicia una invocacin de m*todo remoto en el se!undo.
(a Li!ura ?.7 muestra la arquitectura de 32I con callback de cliente. ,omparada con la
arquitectura básica de 32I, se puede observar que en este caso se necesitan dos
conjuntos de proxies, uno para la interfaz remota del servidor, como en la arquitectura
básica de 32I, y otro para una interfaz adicional, la interfaz remota del cliente. (a
interfaz remota del cliente proporciona un m*todo remoto que puede invocar el servidor
a trav*s del callback.
,omo ejemplo, se incrementará la aplicacin HolaMundo, presentada en el cap'tulo
anterior, de forma que el objeto cliente se re!istre con el servidor para callback y
entonces se le notifique cualquier re!istro de otro objeto cliente para callback con el
servidor.
Incremento .!2342E E& 56RRE576 8R!M!7I5!9ME37E, 42I:;& ! M<
ME &2E3! MEJ6R !986 56M6 =E>7E3&I?3@ "ER6 42EA! ! 72
5RI7ERI61 de la parte cliente para callbacB de cliente
$ara el callback, el cliente debe proporcionar un m*todo remoto que permita al servidor
notificarle el evento correspondiente. Esto puede #acerse de una forma similar a los
m*todos remotos del objeto servidor. En la si!uiente subseccin se describe la sinta)is
necesaria para llevar a cabo esto.
La interfaz remota de cliente
Es importante recordar que el objeto servidor proporciona una interfaz remota que
declara los m*todos que un objeto cliente puede invocar. $ara el callback, es necesario
que el objeto cliente proporcione una interfaz remota similar. Se le denominará interfaz
remota de cliente(por ejemplo, InterfazCallbackCliente ", por oposicin a la interfaz
remota de servidor (por ejemplo, InterfazCallbackServidor". (a interfaz remota de
cliente debe contener al menos un m*todo que será invocado por el servidor en el
callback. ,omo ejemplo, se describe la si!uiente interfaz remota de cliente%
public interface Interfaz,allbacS,liente
extends java.rmi.Remote {
// Este método remoto es invocado por un servidor
// que realice un callbacB al cliente que implementa
// esta interfaz.
// El parámetro es una cadena de caracteres que
// contiene información procesada por el cliente
// una vez realizado el callbacB.
// Este método devuelve un mensaje al servidor.
public Strin notificame!Strin mensaje"
t#ro$s java.rmi.RemoteException%
> -- final de la interfaz
El servidor debe invocar el m*todo notificame cuando realiza el callback, pasando como
ar!umento una cadena de caracteres (String". @na vez recibido el callback, el cliente
utiliza esta cadena para componer otra cadena que devuelve al servidor.
La implementación de la interfaz remota de cliente
&l i!ual que la interfaz remota de servidor, es necesario implementar la interfaz remota
de cliente en una clase, denominada ImplCallbackCliente en el ejemplo, tal y como se
muestra a continuacin%
import java.rmi.&%
import java.rmi.server.&%
public class 'mpl(allbac)(liente extends *nicastRemote+bject
implements 'nterfaz(allbac)(liente {
public 'mpl(allbac)(liente!" t#ro$s RemoteException {
super!"%
}
public Strin notificame !Strin mensaje" {
Strin mensajeRet ,-(allbac) recibido. - / mensaje%
S0stem.out.println!mensajeRet"%
return mensajeRet%
}
> -- final clase Impl,allbacS,liente
En este ejemplo el m*todo de callback notificame simplemente imprime la cadena de
caracteres que le pasa el servidor como ar!umento, y devuelve otra cadena a dic#o
servidor.
&l i!ual que la interfaz remota de servidor, se debe utilizar el compilador rmic con la
implementacin de la interfaz remota de cliente para !enerar los proxies necesarios en
tiempo de ejecucin.
Incremento de la clase cliente
En la clase del objeto cliente, se necesita aUadir cdi!o al cliente para que instancie un
objeto de la implementacin de la interfaz remota de cliente. & continuacin, se re!istra
con el servidor una referencia al objeto utilizando un m*todo remoto proporcionado por
el servidor (v*ase la pr)ima seccin, VIncremento de la parte servidora para callback
de clienteW". @n ejemplo de cmo debe realizarse esto se muestra a continuacin%
Interfaz,allbacSServidor # F
(Interfaz,allbacSServidor" /amin!.looSup(@3(3e!istro"9
Interfaz,allbacS,liente obj,allbacS F
ne4 Impl,allbacS,liente("9
-- re!istrar el objeto para callback
#.re!istrar,allbacS(obj,allbacS"9
(as fi!uras entre la ?.8 #asta la ?.; presentan el cdi!o del soft4are de la parte cliente
para la aplicacin HolaMundo modificada.
Incremento de la parte servidora para callbacB de cliente
En la parte del servidor, se necesita aUadir un m*todo remoto para que el cliente pueda
re!istrarse para callback. En el caso más sencillo, la cabecera del m*todo puede ser
análo!a a la si!uiente%
public void re!istrar,allbacS(
// Se puede eleir el nombre de método deseado
'nterfaz(allbac)(liente obj(allbac)(liente
" t#ro4s java.rmi.3emoteE)ception9
,omo ar!umento se pasa una referencia a un objeto que implementa la interfaz remota
de cliente (InterfazCallbackCliente, no ImplCallbackCliente". +ambi*n se puede
proporcionar un m*todo eliminarRegistroCallback, para que un cliente pueda cancelar
el re!istro (de forma que no reciba más callbacks". (a implementacin de estos
m*todos, as' como la implementacin de un m*todo local hacerCallbacks X para
realizar los callbacks X se muestra en la fi!ura ?.=. (a fi!ura ?.< muestra el fic#ero con
la interfaz del servidor aumentado con las cabeceras de los m*todos adicionales. (a
fi!ura ?.? muestra el cdi!o para el objeto servidor, que queda sin modificar respecto a
la anterior versin, presentada en el cap'tulo anterior.
El servidor necesita emplear una estructura de datos que manten!a una lista de las
referencias a la interfaz de cliente re!istradas para callbacks. En el cdi!o de ejemplo,
un objeto ector es utilizado para este propsito, aunque se puede sustituir por cualquier
otra estructura de datos apropiada. ,ada llamada a registrarCallback implica aUadir una
referencia al vector, mientras que cada llamada a eliminarRegistroCallback supone
borrar una referencia del vector.
En el ejemplo, el servidor realiza un callback (mediante el m*todo hacerCallbacks"
siempre que se lleva a cabo una llamada a registrarCallback, donde se env'a al cliente a
trav*s de callback, el número de clientes actualmente re!istrados. En otras aplicaciones,
los callbacks se pueden activar por otros eventos y pueden !estionarse a trav*s de un
manejador de eventos.
En el ejemplo, un cliente elimina su re!istro despu*s de un determinado periodo de
tiempo. En las aplicaciones reales, la cancelacin del re!istro se puede realizar al final
de la sesin del cliente (tal como en el caso de una sesin de chat o en una sesin de
subastas".
"asos para construir una aplicación RMI con callbacB de cliente
En las si!uientes pá!inas se presenta una descripcin revisada del procedimiento para
construir una aplicacin 32I paso a paso, permitiendo callback de cliente.
Algoritmo para desarrollar el software de la parte del servidor
1. (rear un directorio donde se almacenen todos los fic#eros enerados por la
aplicación.
2. Especificar la interfaz remota de servidor en Inter%a-5allbacB&ervidor.java.
(ompilarla 0 revisarla #asta que no exista nin3n error de sintaxis.
4. 'mplementar la interfaz en Impl5allbacB&ervidor.java. (ompilarlo 0 revisarlo
#asta que no exista nin3n error de sintaxis.
5. *tilizar el compilador R6' rmic para procesar la clase de la implementación
0 enerar los fic#eros stub 0 sBeleton para el objeto remoto.
rmic 'mpl(allbac)Servidor
7os fic#eros enerados se pueden encontrar en el directorio como
Impl5allbacB&ervidorC&Bel.class 0 Impl5allbacB&ervidorC&tub.class. 7os
pasos 4 0 5 deben repetirse cada vez que se cambie la implementación de la
interfaz.
8. +btener una copia del fic#ero class de la interfaz remota del cliente.
9lternativamente: obtener una copia del fic#ero fuente para la interfaz
remota 0 compilarlo utilizando javac para enerar el fic#ero class de la
interfaz Inter%a-5allbacB5liente.class.
;. (rear el prorama correspondiente al objeto servidor &ervidorEjemplo.java.
(ompilarlo 0 revisarlo #asta que no exista nin3n error de sintaxis.
<. +btener una copia del fic#ero stub de la interfaz remota del cliente
Impl5allbacB5lienteC&tub.class.
=. 9ctivar el objeto servidor
java ServidorEjemplo
Algoritmo para desarrollar el software de la parte cliente
1. (rear un directorio donde se almacenen todos los fic#eros enerados por la
aplicación.
2. Especificar la interfaz remota de cliente en Inter%a-5allbacB5liente.java.
(ompilarla 0 revisarla #asta que no exista nin3n error de sintaxis.
4. 'mplementar la interfaz en Impl5allbacB5liente.java. (ompilarlo 0 revisarlo
#asta que no exista nin3n error de sintaxis.
5. *tilizar el compilador R6' rmic para procesar la clase de la implementación
Impl5allbacB5liente.class 0 enerar los fic#eros stub 0 sBeleton
Impl5allbacB5lienteC&Bel.class 0 Impl5allbacB5lienteC&tub.class para el
objeto remoto.
rmic 'mpl(allbac)(liente
7os fic#eros enerados se pueden encontrar en el directorio como
Impl5allbacB5lienteC&Bel.class 0 Impl5allbacB5lienteC&tub.class. 7os pasos
4 0 5 deben repetirse cada vez que se cambie la implementación de la
interfaz.
8. +btener una copia del fic#ero class de la interfaz remota del servidor.
9lternativamente: obtener una copia del fic#ero fuente para la interfaz
remota 0 compilarlo utilizando javac para enerar el fic#ero class de la
interfaz Inter%a-.
;. (rear el prorama correspondiente al objeto cliente 5lienteEjemplo.java.
(ompilarlo 0 revisarlo #asta que no exista nin3n error de sintaxis.
<. +btener una copia del fic#ero stub de la interfaz remota del servidor
Impl5allbacB&ervidorC&tub.class.
=. 9ctivar el objeto cliente
java (lienteEjemplo
(a fi!ura ?.B muestra los fic#eros que se necesitan en los dos e)tremos, cliente y
servidor, cuando se utiliza callback de cliente. (,omo se mencion en el cap'tulo
anterior, desde la versin 5.7 de 0ava no se requieren clases skeleton en las aplicaciones
32I. (as funciones de las clases skeleton se realizan a trav*s de una t*cnica
denominada (#)%#*&+!."
Stub downloading
En la arquitectura de un sistema de objetos distribuidos se requiere un prox! para
interactuar con la llamada a un m*todo remoto de un objeto cliente. En 0ava 32I, este
prox! o intermediario es el stub de la interfaz remota del servidor. En el cap'tulo
anterior se describieron la forma en la que se !eneran los proxies de la interfaz remota
del servidor (ambos el stub y el skeleton" mediante el compilador 32I rmic. (a clase
stub !enerada debe estar en el nodo cliente en tiempo de ejecucin cuando un pro!rama
cliente se ejecute. Esto se puede resolver colocando manualmente el fic#ero class del
stub en el mismo paquete o directorio que el pro!rama del objeto cliente.
0ava 32I proporciona un mecanismo que permite que los clientes obten!an
dinámicamente los stubs necesarios Ydevelopen.java.sun.com, 7Z. 2ediante stub
donloading "&!,-&$, no se necesita una copia de la clase del stub en el nodo cliente.
$or el contrario, *ste se transmite bajo demanda desde un servidor 4eb al nodo cliente
cuando se activa dic#o cliente.
Stub do"nloading utiliza la V#abilidad de descargar dinámicamente soft4are 0ava de
cualquier @3( a una máquina virtual 0ava (012, #ava irtual Machine" ejecutándose
en un proceso separado, normalmente en un sistema f'sico diferenteW
Yjava.sun.com-products, 5Z. 2ediante el uso de stub do"nloading, el desarrollador
almacena una clase stub en un servidor 4eb como un documento 4eb, que puede ser
descargado (utilizando M++$" cuando un objeto cliente se ejecuta, de la misma forma
que se lleva a cabo la descarga de .//%#'s. El uso de M++$ para descar!ar applets se
discutirá en el ,ap'tulo 55.
&l i!ual que antes, un servidor e)porta un objeto contactando con el re!istro 32I y
re!istrando una referencia remota al objeto, especificando un nombre simblico para la
referencia. Si se desea utilizar stub do"nloading, el servidor debe tambi*n indicar al
re!istro el @3( donde se encuentra almacenado la clase stub. (os mecanismos para
realizar esto se presentarán en una seccin posterior.
.e la misma forma que antes, un cliente que desee invocar un m*todo remoto de un
objeto e)portado contacta con el re!istro 32I en el nodo servidor para traer la
referencia remota a trav*s del nombre. Sin stub do"nloading, el objeto stub (un fic#ero
class 0ava" debe colocarse en el nodo cliente manualmente y debe ser localizable por la
máquina virtual 0ava. Si se utiliza stub do"nloading (es decir, se #an realizado los pasos
necesarios descritos en el párrafo anterior con el objeto servidor", entonces se puede
obtener dinámicamente la clase stub de un servidor M++$ de forma que puede
interactuar con el objeto cliente y el soporte en tiempo real de 32I. (a clase stub
descargada no es persistente, es decir, no se almacena de forma permanente en el nodo
cliente, sino que por el contrario el sistema libera la clase correspondiente cuando la
sesin del cliente finaliza. Si no se utiliza cac#e en el servidor 4eb, cada ejecucin de la
clase cliente requiere la descarga del stub del servidor 4eb.
(a fi!ura ?.5D muestra la interaccin entre el objeto cliente, el objeto servidor y el
re!istro 32I cuando se utiliza stub do"nloading. $ronto se describirán los al!oritmos
necesarios para ejecutar una aplicacin mediante el uso de stub do"nloading. &ntes, se
debe presentar un tema relacionado% el !estor de se!uridad de 32I.
El gestor de seguridad de RMI
&unque stub do"nloading es una caracter'stica útil, su uso supone un problema para el
sistema de se!uridad. Este problema no está asociado al uso de 32I, sino a la descarga
de objetos en !eneral. ,uando un objeto como un stub 32I se transfiere desde un nodo
remoto, su ejecucin entraUa el ries!o de ataques maliciosos al nodo local. .ebido a que
un objeto descargado procede de un ori!en desconocido, la ejecucin de su cdi!o, si
no se restrin!e, podr'a causar estra!os en el nodo local, provocando daUos similares a
los causados por un Vvirus de computadorW Ycert.or!, 8Z.
$ara evitar los problemas de se!uridad del uso de stub do"nloading, 0ava proporciona
una clase denominada RMISecurit!Manager. @n pro!rama 32I puede instanciar un
objeto de esta clase. @na vez instanciado, el objeto supervisa durante la ejecucin del
pro!rama todas las acciones que puedan suponer un ries!o de se!uridad. Estas acciones
incluyen el acceso a fic#eros locales y la realizacin de cone)iones de red, ya que
dic#as acciones podr'an suponer modificaciones de los recursos locales no deseadas o
mal uso de los recursos de red. En particular, el soporte en tiempo real de 32I requiere
que un proceso servidor instale un 0#s'( "# s#01(&"." antes de e)portar cualquier
objeto que requiera stub do"nloading, y que un cliente instale un !estor de se!uridad
antes de que puede realizar la descarga del stub.
$un%ue la noci&n de gestor de seguridad no se introdu'o en el cap(tulo anterior) se
recomienda su uso en todas las aplicaciones RMI) independientemente de %ue se utilice
stub do"nloading o no* $or defecto, un !estor de se!uridad 32I es muy restrictivo% no
permite acceso a los fic#eros y slo permite cone)iones al nodo ori!en. (Esta restriccin
de acceso tambi*n se utiliza en las descargas de applets*" Esta restriccin, sin embar!o,
no permite a un objeto cliente 32I contactar con el (#0&s'( RMI del nodo del objeto
servidor y tampoco le permite llevar a cabo stub do"nloading. Es posible relajar estas
condiciones instalando un fic#ero especial conocido como )&$2#( "# /%3'&$. "#
s#01(&".", cuya sinta)is especifica el tipo de restriccin que un !estor de se!uridad,
incluyendo los !estores de se!uridad 32I, debe utilizar. $or defecto, e)iste un fic#ero
de pol'tica de se!uridad en un directorio especial de cada sistema que utiliza 0ava. (as
restricciones especificadas en el fic#ero de pol'ticas de se!uridad del sistema X las
restricciones por defecto anteriormente mencionadas X serán empleadas por el !estor de
se!uridad a menos que se sobreescriban mediante el uso de un fic#ero de pol'ticas
alternativo. &lternativamente, una aplicacin puede especificar un fic#ero de pol'ticas
de se!uridad, de forma que las restricciones las impone la propia aplicacin. $ara los
ejercicios realizados por el lector, se recomienda que se especifique un fic#ero de
se!uridad con cada aplicacin que se ejecute, de forma que se ten!a control
e)clusivamente sobre las restricciones impuestas en la aplicacin del lector, sin afectar a
las restricciones de otros pro!ramas. En al!unos sistemas, puede ocurrir que un usuario
normal no ten!a privile!io de acceso para modificar el fic#ero por defecto de pol'ticas
de se!uridad de 0ava.
& continuacin, se describe cmo una aplicacin utiliza el !estor de se!uridad de 32I.
Instanciación de un 8estor de &e$uridad en un pro$rama RMI
(a clase RMISecurit!Manager se puede instanciar tanto en el objeto cliente como en el
objeto servidor utilizando la si!uiente sentencia%
System.setSecurityManager(new RMISecurityManager());
Esta sentencia deber'a aparecer antes del cdi!o de acceso al re!istro 32I. (as fi!uras
?.55 y ?.57 muestran los ejemplos del pro!rama HolaMundo, presentados en el cap'tulo
anterior, pero instanciando un !estor de se!uridad.
9a sinta#is de un %ichero de políticas de se$uridad de Java
@n fic#ero de pol'ticas de se!uridad de 0ava es un fic#ero de te)to que contiene cdi!os
que permiten especificar la concesin de permisos espec'ficos. & continuacin se
muestra un fic#ero t'pico 'ava*polic! para una aplicacin 32I.
grant {
// Este permiso permite a los clientes RMI realizar
// conexiones e soc!ets a los puertos p"#licos e
// cual$uier computaor.
// Si se arranca un puerto en el registro RMI en este
// rango% no existir& una 'iolaci(n e acceso e
// conexi(n.
// permission )a'a.net.Soc!et*ermission +,-./012
344546%
// +connect%accept%resol'e6;
// Este permiso permite a los soc!ets acceer al
puerto
// 7/% el puerto por e8ecto 9::* $ue el cliente
// necesita para contactar con el ser'ior 9::* para
// stu# ownloaing
permission )a'a.net.Soc!et*ermission +,-7/6%
+connect6;
};
Se recomienda al lector que cuando realice los ejercicios, #a!a una copia de este fic#ero
para la aplicacin con el nombre 'ava*polic! en el mismo directorio tanto en el nodo del
objeto cliente como en el nodo del objeto servidor.
,uando se active el cliente, #ay que utilizar la opcin del mandato que permite
especificar que el proceso cliente debe tener los permisos definidos en el fic#ero de
pol'ticas, de la si!uiente forma%
)a'a ;<)a'a.security.policy=)a'a.policy >lienteE)emplo
.el mismo modo, el servidor debe activarse del si!uiente modo%
)a'a ;<)a'a.security.policy=)a'a.policy Ser'iorE)emplo
Estos dos mandatos asumen que el fic#ero de pol'ticas se llama 'ava*polic! y está
disponible en el directorio actual de la parte servidora y cliente.
@na descripcin detallada de las pol'ticas de se!uridad 0ava, incluyendo una e)plicacin
de la sinta)is utilizada en este fic#ero, se puede encontrar en Yjava.sun.com-marSetin!,
:Z.
2so de stub doDnloadin$ ' un %ichero de políticas de se$uridad
5. Si debe descargarse el stub de un servidor M++$, transfiera la clase stub a un
directorio apropiado del servidor M++$, por ejemplo, al directorio s'14s del nodo
444.miempresa.com, y ase!úrese de que el permiso de acceso del fic#ero es de
lectura para todos los usuarios.
7. ,uando se activa el servidor, se debe especificar las si!uientes opciones del
mandato%
)a'a ;<)a'a.rmi.ser'er.co#ase=?@RAB
2<)a'a.security.policy=
?ruta completa el 8icCero e polDticas e
seguriaB
donde
[@3(\ es el @3( del directorio donde se encuentra la clase stub9 por ejemplo,
#ttp%--444.miempresa.com-stubs-.
Abs*rvese la barra del final del @3(, que indica que el @3( especifica un
directorio, no un fic#ero.
[ruta completa del fic#ero de pol'ticas de se!uridad\ especifica el fic#ero de
pol'ticas de se!uridad de la aplicacin9 por ejemplo, java.security, si el fic#ero
java.security se encuentra en el directorio actual.
>or ejemplo:
)a'a ;
<)a'a.rmi.ser'er.coe#ase=Cttp-//www.miempresa.com/stu#s/
2<)a'a.security.policy=)a'a.security 9olaMunoSer'ior
(todo en una l'nea"
arrancará la aplicacin HolaMundoServidor y permitirá realizar stub do"nloading del
directorio stubs del servidor 4eb de 444.miempresa.com.
(a fi!ura ?.58 muestra el conjunto de fic#eros que se necesitan para una aplicacin 32I
y donde se deben colocar, suponiendo stub do"nloading dinámico. ($or simplicidad, se
asume que la aplicacin no usa callback de cliente. Se podr'an aUadir los fic#eros
necesarios para realizar callback de cliente, si se deseará."
En la parte del servidor, los fic#eros necesarios son los fic#eros class del servidor, la
interfaz remota, la implementacin de la interfaz (!enerada por 'avac", el fic#ero class
del stub (!enerado por rmic", la clase del skeleton (!enerado por rmic", y el fic#ero de
pol'ticas de se!uridad de la aplicacin. En la parte cliente, los fic#eros que se necesitan
son el fic#ero class del cliente, el fic#ero class de la interfaz remota del servidor y el
fic#ero de pol'ticas de se!uridad de la aplicacin. Linalmente, el fic#ero class del stub
se debe almacenar en el nodo M++$ del cual se descarga el stub.
!l$oritmos para construir una aplicación RMI, ue permita stub doDnloadin$
& continuacin se realiza una descripcin del procedimiento paso a paso para la
construccin de una aplicacin 32I, teniendo en cuenta el uso de stub do"nloading. .e
nuevo, por cuestiones de simplicidad, se #an obviado los detalles para el callback de
cliente.
Algoritmo para desarrollar el software de la parte del servidor
1. (rear un directorio donde se almacenen todos los fic#eros enerados por la
aplicación.
2. Especificar la interfaz remota de servidor en Inter%a-Ejemplo.java.
(ompilarla 0 revisarla #asta que no exista nin3n error de sintaxis.
4. 'mplementar la interfaz en ImplEjemplo.java. (ompilarlo 0 revisarlo #asta
que no exista nin3n error de sintaxis.
5. *tilizar el compilador R6' rmic para procesar la clase de la implementación
0 enerar los fic#eros stub 0 sBeleton para el objeto remoto.
rmic ImplE)emplo
7os fic#eros enerados se pueden encontrar en el directorio como
ImplEjemploC&Bel.class 0 ImplEjemploC&tub.class. 7os pasos 4 0 5 deben
repetirse cada vez que se cambie la implementación de la interfaz.
8. (rear el prorama del objeto servidor &ervidorEjemplo.java. (ompilarlo 0
revisarlo #asta que no exista nin3n error de sintaxis.
;. Si se desea stub doDnloadin$: copiar el fic#ero stub en un directorio
apropiado del servidor ?@@>.
<. Si se utiliza el reistro R6' 0 no #a sido 0a activado: activarlo. >or ejemplo.
rmiregistry ?n"mero e puerto% ./EE por e8ectoB
&lternativamente, se puede codificar la activacin en el pro!rama del objeto
servidor.
=. (onstruir un fic#ero de polAticas de seuridad para la aplicación
denominado java.polic' !u otro nombre": 0 colocarlo en un directorio
apropiado o en el directorio actual.
B. 9ctivar el servidor: especificando !1" el campo codebase si se utiliza stub
doDnloadin$: 0 !2" el fic#ero de polAticas de seuridad.
)a'a ;
<)a'a.rmi.ser'er.coe#ase=Cttp-//noo.om.eu/stu#s/
2<)a'a.security.policy=)a'a.policy Ser'iorE)emplo
Este mandato se ejecuta en una 3nica lAnea: aunque se puede utilizar un
carácter de continuación de lAnea !CDE" en un sistema *F'G. Se recomienda
poner el mandato en un fic#ero de texto ejecutable !tal como
ejec&ervidor.bat en un sistema Hindo$s o ejec&ervidor en un sistema *F'G"
0 ejecutar el fic#ero para arrancar el servidor.
>ara la aplicación EolaMundo: el fic#ero ejec&ervidor.bat contendrAa esta
lAnea.
)a'a 2<)a'a.security.policy=)a'a.policy
2<)a'a.rmi.ser'er.coe#ase=
Cttp-//www.csc.calpoly.eu/Imliu/stu#s/ 9olaMunoSer'ior
Je nuevo: no deberAa #aber saltos de lAneas en el fic#ero
Algoritmo para desarrollar el software de la parte cliente
1. (rear un directorio donde se almacenen todos los fic#eros enerados por la
aplicación.
2. +btener una copia del fic#ero class de la interfaz remota del servidor.
9lternativamente: obtener una copia del fic#ero fuente para la interfaz
remota 0 compilarlo utilizando javac para enerar el fic#ero class de la
interfaz Inter%a-Ejemplo.
4. Si se desea utilizar stub doDnloadin$: obtener una copia del fic#ero class
del stub !supónase que se llama ImplEjemploC&tub.class" 0 colocarlo en el
directorio actual.
5. (onstruir un fic#ero de polAticas de seuridad para la aplicación
denominado java.polic' !u otro nombre": 0 colocarlo en un directorio
apropiado o en el directorio actual.
8. 9ctivar el cliente: especificando el fic#ero de polAticas de seuridad.
)a'a 2<)a'a.security.policy=)a'a.policy >lienteE)emplo
Este mandato se ejecuta en una 3nica lAnea: aunque se puede utilizar un
carácter de continuación de lAnea !CDE" en un sistema *F'G. Se recomienda
poner el mandato en un fic#ero de texto ejecutable !tal como ejec5liente.bat
en un sistema Hindo$s o ejec5liente en un sistema *F'G" 0 ejecutar el
fic#ero para arrancar el cliente.
>ara la aplicación EolaMundo: el fic#ero ejec5liente.bat contendrAa esta
lAnea.
)a'a 2<)a'a.security.policy=)a'a.policy 9olaMuno>liente
Je nuevo: no deberAa #aber saltos de lAneas en el fic#ero
Si se utiliza callbacS de cliente, deben insertarse en este al!oritmo los pasos adicionales
descritos en la seccin anterior V$asos para construir una aplicacin 32I con callbacS
de clienteW.
Resumen
En este cap'tulo se #an analizado al!unas de las caracter'sticas avanzadas del &$I de
0ava 32I. &unque estas caracter'sticas no son parte in#erente del paradi!ma de objetos
distribuidos, son interesantes y útiles para al!unas aplicaciones.
5allbacB de cliente
• El callback de cliente es útil para las aplicaciones que deseen que el servidor les
notifique la ocurrencia de al!ún evento.
• El callback de cliente permite que un objeto servidor realice una invocacin de
m*todo remoto de un cliente a trav*s de la referencia a una interfaz remota de dic#o
cliente.
• $ara dotar a la aplicacin de callback de cliente, el soft4are de la parte cliente debe
proporcionar una interfaz remota, instanciar un objeto que implemente dic#a
interfaz y pasar la referencia del objeto al servidor. El objeto servidor !uarda estas
referencias del cliente en una estructura de datos. ,uando el evento esperado ocurre,
el objeto servidor invoca un m*todo callback (definido en la interfaz remota del
cliente", pasando los datos a los clientes apropiados.
• Se necesitan dos conjuntos de stub y skeleton% uno para las interfaz remota del
servidor y el otro para la interfaz remota del cliente.
&tub doDnloadin$ ' $estor de se$uridad
• (a caracter'stica de stub do"nloading permite que un cliente pueda car!ar una clase
stub en tiempo de ejecucin.
• Stub do"nloading requiere la confi!uracin de la propiedad
'ava*rmi*server*codebase cuando se inicia el servidor% esta propiedad debe
confi!urarse con el directorio de un servidor M++$ donde se encuentre almacenada
la copia del fic#ero class del stub y accesible a todos los usuarios.
• Stub do"nloading requiere la instalacin de un !estor de se!uridad 32I tanto en la
parte cliente como en la servidora.
• $ara llevar a cabo stub do"nloading, es necesario el uso de un !estor de se!uridad,
ya que la ejecucin de un objeto descargado de una máquina desconocida puede
suponer una amenaza para el computador cliente.
• @n !estor de se!uridad lleva a cabo las restricciones especificadas en un fic#ero de
pol'ticas de se!uridad de 0ava, que puede ser el fic#ero de pol'ticas del sistema o un
fic#ero de pol'ticas aplicado solamente a una aplicacin individual.
• En este cap'tulo se mostr un ejemplo de fic#ero de pol'ticas de se!uridad para
aplicaciones 32I.
• $or cuestiones de se!uridad, el uso de los !estores de se!uridad es recomendable en
todas las aplicaciones 32I, independientemente de que utilicen stub do"nloading o
no.
Ejercicios [SE P!R"A P#ER E# IMPERA$I% E#
%E& !E I#'I#I$I%(
5. En el conte)to de 0ava 32I, ]qu* es el callback de cliente^ ]$or qu* es útil^
7. $robar el pro!rama ejemplo Callback en uno o más máquinas.
a. ,rear una carpeta (denominada callback" para este ejercicio. ,rear dos
subcarpetas X con los nombres Servidor y Cliente, respectivamente X en el $,.
,opiar los fic#eros fuente en las carpetas Servidor y Cliente respectivamente.
b. Se!uir los al!oritmos presentados en el cap'tulo para confi!urar y ejecutar los
objetos servidor y cliente. Escribir un informe indicando las acciones realizadas
y las salidas.
c. &rrancar varios clientes sucesivamente. Escribir en el informe las acciones y las
salidas de los pro!ramas.
d. ,opiar el contenido de la carpeta callback en una carpeta nueva. 2odificar los
fic#eros fuente en la nueva carpeta, de forma que el servidor notifique solamente
a un cliente cuando se #ayan re!istrado para callback exactamente tres clientes.
2ostrar los cambios realizados en los fic#eros fuente.
e. 1olviendo a la carpeta callback, arrancar un servidor y un cliente, especificando
un tiempo de duracin del cliente de <DD se!undos. 2ientras el cliente espera
por callback, abortar el proceso cliente mediante el uso de ,trl-,. 3ápidamente
arrancar un nuevo proceso cliente de forma que el servidor intenta realizar un
callback a todos los clientes re!istrados. &puntar lo que se observa.
3ealizar cambios al cdi!o fuente de forma que los problemas observados no
ocurran. .escribir los cambios realizados a los pro!ramas. Entre!ar los listados
fuente modificados.
8. En un ejercicio del cap'tulo anterior, se ped'a utilizar 32I para escribir una
aplicacin que fuera un prototipo de un sistema de encuestas de opinin. 2odificar
la aplicacin para que cada cliente proporcione una interfaz de usuario de forma que
se pueda realizar un voto. &dicionalmente, se debe mostrar en la pantalla del usuario
el recuento actual siempre que se realice un nuevo voto (sea desde este cliente o
desde cualquier otro cliente".
3ecopilar todos los listados de los fic#eros fuentes, incluyendo los fic#eros de las
interfaces. Se recomienda una demostracin de los pro!ramas en el laboratorio.
5. En el contexto de Kava R6': Lqué es stub doDnoladin$M L>or qué es 3tilM
8. Experimentar con stub doDnloadin$ utilizando el ejemplo presentado en la
Sección =.4 de este capAtulo. 7os fic#eros deben encontrarse en la carpeta
stubAoDnloadin$ de los ejemplos de proramas.
a. (rear una carpeta !llamada stubAoDnloadin$" para este ejercicio. (rear
dos subcarpetas en el >( 0 denominarlas &ervidor 0 (liente:
respectivamente. (opiar los fic#eros R6' del ejemplo EolaMundo en la
carpeta correspondiente.
b. (ompilar los fic#eros. *tilizar rmic para enerar los fic#eros stub 0
sBeleton en la carpeta &ervidor. (opiar el fic#ero class stub en la carpeta
5liente.
c. 9rrancar un servidor de la carpeta &ervidor sin especificar stub
doDnloadin$ !es decir: sin confiurar la propiedad codebase al arrancar
el intérprete Kava". 9 continuación: arrancar un cliente de la carpeta
5liente. (omprobar que funcionan de la forma esperada.
d. En la carpeta 5liente: borrar el fic#ero EolaMundoImplC&tub.class.
9rrancar un cliente de nuevo. JeberAa obtenerse una notificación de
excepciones Kava en tiempo de ejecución debido a la ausencia de la
clase stub.
e. Nolviendo a la carpeta &ervidor: copiar el fic#ero
EolaMundoImplC&tub.class a un servidor $eb desde el que #a0a
acceso: en un directorio denominado stubs !o al3n otro nombre".
Jonde sea aplicable: establecer las protecciones de acceso al directorio
stubs 0 al fic#ero stub: de forma que se pueda leer por todo el mundo.
9rrancar un servidor desde la carpeta &ervidor: esta vez especificando
stub doDnloadin$ !es decir: confiurando la propiedad codebase para
permitir que se realice stub doDnloadin$ desde el directorio donde se
encuentra el fic#ero class del stub".
f. Nolviendo a la carpeta 5liente: probar a ejecutar el cliente de nuevo. Si
las funciones de stub doDnloadin$ funcionan como se espera: el cliente
debe funcionar esta vez.
. >robar a duplicar la carpeta 5liente 0 arrancar otros clientes en
diferentes sistemas de la misma forma: utilizando stub doDnloadin$.
Escribir un informe describiendo el experimento.
;. Repetir el ejercicio en el ejemplo 5allbacB. Este vez: el cliente debe poder
realizar un stub doDnloadin$ del stub del servidor dinámicamente: mientras
que el servidor debe poder obtener el stub del cliente dinámicamente
también.
Se recomienda que la primera vez que se realice este experimento: se
utilice una copia de los fic#eros stub. 9 continuación borrar el stub de
servidor de la carpeta cliente: 0 probar a ejecutar el cliente con stub
doDnloadin$. (onsecutivamente: borrar el stub del cliente de la carpeta
servidor: 0 probar a ejecutar el servidor con stub doDnloadin$. Escribir un
informe describiendo el experimento.
Referencias
5. .escar!a dinámica de cdi!o utilizando 32I,
#ttp%--java.sun.com-products-jdS-5.7-docs-!uide-rmi-codebase.#tml
7. Introduccin a la computacin distribuida con 32I,
#ttp%--developer.java.sun.com-developer-online+rainin!-rmi-32I.#tml
8. ,E3+_ ,oordination ,enter, ,E3+-,, ,omputer 1irus 3esources,
#ttp%--444.cert.or!-ot#er`sources-viruses.#tml
:. 0ava 3emote 2et#od Invocation X ,omputacin distribuida para 0ava,
#ttp%--java.sun.com-marSetin!-collateral-javarmi.#tml
'iguras
F&01(. 5.1 Sondeo (polling" frente a callback.
F&01(. 5.2 (a arquitectura de 32I con callback de cliente.
F&01(. 5.3 Lic#ero InterfazCallbackCliente*'ava de la aplicacin HolaMundo
modificada.
. import )a'a.rmi.,;
0
5 /,,
4 , Esto es una inter8az remota para ilustrar el
5 , callback e cliente.
6 , FautCor M. A. Aiu
7 ,/
8
9 public interface InterfazCallbackCliente
10 extens )a'a.rmi.Remote{
11 // Este mGtoo remoto se in'oca meiante callback
12 // e ser'ior% e 8orma $ue realiza un callback a
13 // un cliente $ue implementa esta inter8az.
14 // Fmessage una caena e caracteres $ue contiene
15 // in8ormaci(n procesaa por el cliente.
16
17 pu#lic 'oi noti8icame(String mensa)e)
18 tCrows )a'a.rmi.RemoteException;
19
20 } // 8in inter8az
F&01(. 5.6 Lic#ero ImplCallbackCliente*'ava de la aplicacin HolaMundo modificada.
. import )a'a.rmi.,;
0 import )a'a.rmi.ser'er.,;
5
1 /,,
4 , Esta clase implementa la inter8az remota
3 , Inter8az>all#ac!>liente.
H , FautCor M. A. Aiu
7 ,/
E
10 public class ImplCallbackCliente extends
UnicastRemoteObject
11 implements InterfazCallbackCliente {
.0
.5 pu#lic Impl>all#ac!>liente () tCrows
RemoteException {
.1 super( );
.4 }
.3
.H pu#lic String noti8icame(String mensa)e){
.7 String mensa)eRet = I>all#ac! reci#io- + J
mensa)e;
.E System.out.println(mensa)eRet);
0/ return mensa)eRet;
0. }
00
05 } // 8in clase Impl>all#ac!>liente
F&01(. 5.7 Lic#ero Cliente+'emplo*'ava de la aplicacin HolaMundo modificada.
. import )a'a.io.,;
0 import )a'a.rmi.,;
5
4 /,,
5 , Esta clase representa el o#)eto cliente para un
6 , o#)eto istri#uio e la clase Impl>all#ac!Ser'ior%
7 , $ue implementa la inter8az remota
8 , Inter8az>all#ac!Ser'ior. :am#iGn acepta callbacks
9 , el ser'ior.
10 ,
11 ,
12 ,
13 , FautCor M. A. Aiu
14 ,/
15
16 public class ClienteEjemplo {
17
18 pu#lic static 'oi main(String argsKL) {
19 try {
20 int puertoRMI;
21 String nom#reMoo;
22 InputStreamReaer ent =
23 new InputStreamReaer(System.in);
24 Nu88ereReaer #u8= new Nu88ereReaer(ent);
25 System.out.println(
26 +Introuce el nom#re e noo el
registro RMI-6);
27 nom#reMoo = #u8.reaAine();
28 System.out.println(
29 +Introuce el n"mero e puerto el
registro RMI-6);
30 String num*uerto = #u8.reaAine();
31 puertoRMI = Integer.parseInt(num*uerto);
32 System.out.println(
33 +Introuce cuantos segunos 'a a
permanecer registrao-6);
34 String uracion:iempo = #u8.reaAine();
35 int tiempo =
Integer.parseInt(uracion:iempo);
36 String @RARegistro =
37 +rmi-//localCost-6J num*uerto J
+/call#ac!6;
38 // N"s$uea el o#)eto remoto y cast al
o#)eto
39 // e la inter8az
40 Inter8az>all#ac!Ser'ior C =
41 (Inter8az>all#ac!Ser'ior)
Maming.loo!up(@RARegistro);
42 System.out.println(+N"s$uea completa +);
43 System.out.println(+El ser'ior ice + J
C.ecir9ola());
44 Inter8az>all#ac!>liente o#)>all#ac! =
45 new Impl>all#ac!>liente();
46 // registrar para callback
47 C.registrar>all#ac!(o#)>all#ac!);
48 System.out.println(+Registrao para
call#ac!.6);
49 try {
50 :Crea.sleep(tiempo,.///);
51 }
52 catcC (InterrupteException exc) { // so#re
el mGtoo sleep
53
C.eliminarRegistro>all#ac!(o#)>all#ac!);
54 System.out.println(+Mo registrao para
call#ac!.6);
55 }
56 } // 8in try
57 catcC (Exception e) {
58 System.out.println(
59 +Excepci(n en >lienteE)emplo- + J e);
60 }
61 } // 8in main
62 } // 8in clase
F&01(. 5.8 Lic#ero InterfazCallbackServidor*'ava de la aplicacin HolaMundo
modificada.
1 import )a'a.rmi.,;
2
3 /,,
4 , Esto es una inter8az remota para ilustrar el
5 , callback e cliente.
6 , FautCor M. A. Aiu
7 ,/
8
9 public interface InterfazCallbackSeridor extends
Remote{
10
11 pu#lic String ecir9ola( )
12 tCrows )a'a.rmi.RemoteException;
13
14 // Este mGtoo remoto permite a un o#)eto
15 // cliente registrarse para callback
16 // Fparam o#)>liente>all#ac! es una
re8erencia
17 // al o#)eto el cliente; el ser'ior lo
18 // utiliza para realizar los callbacks
19
20 pu#lic 'oi registrar>all#ac!(
21 Inter8az>all#ac!>liente o#)>all#ac!>liente)
22 tCrows )a'a.rmi.RemoteException;
23
24 // Este mGtoo remoto permite a un o#)eto
25 // cliente cancelar su registro para
callback
26
27 pu#lic 'oi eliminarRegistro>all#ac!(
28 Inter8az>all#ac!>liente o#)>all#ac!>liente)
29 tCrows )a'a.rmi.RemoteException;
30 }
F&01(. 5.7 Lic#ero ImplCallbackServidor*'ava de la aplicacin HolaMundo modificada.
. import )a'a.rmi.,;
2 import )a'a.rmi.ser'er.,;
3 import )a'a.util.Oector;
4
5 /,,
6 , Esta clase implementa la inter8az remota
7 , Inter8az>all#ac!Ser'ior.
8 , FautCor M. A. Aiu
9 ,/
10
11 pu#lic class Impl>all#ac!Ser'ior extens
@nicastRemoteP#)ect
12 implements Inter8az>all#ac!Ser'ior {
13
14 pri'ate Oector lista>lientes;
15
16
17 pu#lic Impl>all#ac!Ser'ior () tCrows
RemoteException {
18 super( );
19 lista>lientes = new Oector();
20 }
21
22 pu#lic String ecir9ola()
23 tCrows )a'a.rmi.RemoteException {
24 return(+9ola Muno6);
25 }
26
27 pu#lic 'oi registrar>all#ac!(
28 Inter8az>all#ac!>liente o#)>all#ac!>liente)
29 tCrows )a'a.rmi.RemoteException {
30 // almacena el o#)eto callback en el 'ector
31 i8 (Q
(lista>lientes.contains(o#)>all#ac!>liente))) {
32
lista>lientes.aElement(o#)>all#ac!>liente);
33 System.out.println(+Mue'o cliente
registrao +);
34 Cacer>all#ac!s();
35 } // 8in i8
36 }
37
38 // Este mGtoo remoto permite a un o#)eto cliente
39 // cancelar su registro para callback
40 // Fparam i es un ienti8icaor para el cliente;
41 // el ser'ior lo utiliza "nicamente para
ienti8icar al cliente registrao.
42 pu#lic syncCronize 'oi
eliminarRegistro>all#ac!(
43 Inter8az>all#ac!>liente o#)>all#ac!>liente)
44 tCrows )a'a.rmi.RemoteException{
45 i8
(lista>lientes.remo'eElement(o#)>all#ac!>liente)){
46 System.out.println(+>liente no
registrao +);
47 } else {
48 System.out.println(
49 +eliminarRegistro- el cliente no
8ue registrao.6
50 }
51 }
52
53 pri'ate syncCronize 'oi Cacer>all#ac!s( )
tCrows )a'a.rmi.RemoteException {
54 // realizar callback e un cliente
registrao
55 System.out.println(
56 ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,Rn6 J
57 +>all#ac! iniciao ;2 +);
58 8or (int i=/; i?lista>lientes.size(); iJJ) {
59 System.out.println(+Cacieno call#ac!
n"mero+J i +Rn6);
60 // con'ertir el o#)eto 'ector a un
o#)eto callback
61 Inter8az>all#ac!>liente prox>liente =
62 (Inter8az>all#ac!>liente)
lista>lientes.elementSt(i);
63 // in'ocar el mGtoo e callback
64 prox>liente.noti8icame(+M"mero e
clientes registraos=6
65 J lista>lientes.size());
66 } // 8in 8or
67
System.out.println(+,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,Rn6
68 J +Ser'ior completo call#ac!s ;2+);
69 } // 8in Cacer>all#ac!s
70
71 } // 8in clase Impl>all#ac!Ser'ior
F&01(. 5.5 Lic#ero Servidor+'emplo*'ava de la aplicacin HolaMundo modificada.
. import )a'a.rmi.,;
0 import )a'a.rmi.ser'er.,;
5 import )a'a.rmi.registry.Registry;
1 import )a'a.rmi.registry.AocateRegistry;
4 import )a'a.net.,;
3 import )a'a.io.,;
H
7 /,,
E , Esta clase representa el o#)eto ser'ior para un
./ , o#)eto istri#uio e la clase >all#ac!% $ue
.. implementa la inter8az remota Inter8az>all#ac!.
.0 , FautCor M. A. Aiu
.5 ,/
.1
1! public class SeridorEjemplo {
.3 pu#lic static 'oi main(String argsKL) {
.H InputStreamReaer ent =
.7 new InputStreamReaer(System.in);
.E Nu88ereReaer #u8= new Nu88ereReaer(ent);
0/ String num*uerto% @RARegistro;
0. try {
00 System.out.println(
05 +Introucir el n"mero e puerto el
registro RMI-6);
01 num*uerto=(#u8.reaAine()).trim();
04 int num*uertoRMI =
Integer.parseInt(num*uerto);
03 arrancarRegistro(num*uertoRMI);
0H Impl>all#ac!Ser'ior o#)Exportao =
07 new Impl>all#ac!Ser'ior( );
0E @RARegistro =
5/ +rmi-//localCost-6 J num*uerto J
+/call#ac!6;
5. Maming.re#in(@RARegistro%
o#)Exportao);
50 System.out.println(+Ser'ior call#ac!
preparao.6);
55 } // 8in try
51 catcC (Exception exc) {
54 System.out.println(
53 +Excepci(n en Ser'iorE)emplo.main- + J
exc);
5H } // 8in catcC
57 } // 8in main
5E
1/ // Este mGtoo arranca un registro RMI en el noo
1. // local% si no existe en el n"mero e puerto
especi8icao.
10 pri'ate static 'oi arrancarRegistro(int
num*uertoRMI)
15 tCrows RemoteException {
11 try {
14 Registry registro =
13
AocateRegistry.getRegistry(num*uertoRMI);
1H registro.list();
17 // Esta llamaa lanza una excepci(n
1E // si el registro no existe
4/ }
4. catcC (RemoteException e) {
40 // Mo existe registro '&lio en el
puerto
45 Registry registro =
41
AocateRegistry.createRegistry(num*uertoRMI);
44 }
43 } // 8in arrancarRegistro
4H
47 } // 8in clase
F&01(. 5.9 ,olocacin de los fic#eros en una aplicacin 32I con callback de cliente.
F&01(. 5.1: Stub do"nloading.
F&01(. 5.11 HolaMundoServidor*'ava #aciendo uso de un !estor de se!uridad.
1 import )a'a.rmi.,;
2 import )a'a.rmi.ser'er.,;
3 import )a'a.rmi.registry.Registry;
4 import )a'a.rmi.registry.AocateRegistry;
5 import )a'a.net.,;
6 import )a'a.io.,;
7
8 /,,
9 , Esta clase representa el o#)eto ser'ior para un
10 , o#)eto istri#uio e la clase 9olaMuno% $ue
11 implementa la inter8az remota Inter8az9olaMuno. Se
12 instala un gestor e seguria para realizar stub
downloading seguro.
13 , FautCor M. A. Aiu
14 ,/
15
16 public class "ola#undoSeridor {
17 pu#lic static 'oi main(String argsKL) {
18 InputStreamReaer ent =
19 new InputStreamReaer(System.in);
20 Nu88ereReaer #u8= new Nu88ereReaer(ent);
21 String num*uerto% @RARegistro;
22 try {
23 System.out.println(
24 +Introucir el n"mero e puerto el
registro RMI-6);
25 num*uerto=(#u8.reaAine()).trim();
26 int num*uertoRMI =
Integer.parseInt(num*uerto);
27
28 $$ arrancar un %estor de se%uridad &
esto es
29 $$ necesario si se utiliza stub
downloading
30 S'stem(setSecurit'#ana%er)
31 ne* R#ISecurit'#ana%er)++,
32
33 arrancarRegistro(num*uertoRMI);
34 Impl9olaMuno o#)Exportao = new
Impl9olaMuno();
35 @RARegistro =
36 +rmi-//localCost-6 J num*uerto J
+/ColaMuno6;
37 Maming.re#in(@RARegistro%
o#)Exportao);
38 System.out.println(
39 +Ser'ior registrao. El registro
contiene-6);
40 // listar los nom#res registraos
actualmente
41 listarRegistro(@RARegistro);
42 System.out.println(+Ser'ior 9ola Muno
preparao.6);
43 } // 8in try
44 catcC (Exception exc) {
45 System.out.println(
46 +Excepci(n en 9olaMunoSer'ior.main- +
J exc);
47 } // 8in catcC
48 } // 8in main
49
50 // Este mGtoo arranca un registro RMI en el noo
51 // local% si no existe en el n"mero e puerto
especi8icao.
52 pri'ate static 'oi arrancarRegistro(int
num*uertoRMI)
53 tCrows RemoteException {
54 try {
55 Registry registro =
56
AocateRegistry.getRegistry(num*uertoRMI);
57 registro.list(); // Esta llamaa lanza
58 // una excepci(n si el registro no
existe
59 }
60 catcC (RemoteException e) {
61 // Mo existe registro '&lio en el
puerto
62 System.out.println(
63 +El registro RMI no se localiza en este
puerto +
64 J num*uertoRMI);
65 Registry registro =
66
AocateRegistry.createRegistry(num*uertoRMI);
67 System.out.println(
68 +Registro RMI creao en el puerto +J
num*uertoRMI);
69 }
70 } // 8in arrancarRegistro
71
72 // Este mGtoo lista los nom#res registraos en
RMI
73 pri'ate static 'oi listarRegistro(String
@RARegistro)
74 tCrows RemoteException%
Mal8orme@RAException {
75 System.out.println(
76 +Registro + J @RARegistro J + contiene- +);
77 String KL nom#res =
Maming.list(@RARegistro);
78 8or (int i=/; i? nom#res.lengtC; iJJ)
79 System.out.println(nom#resKiL);
80 } // 8in listarRegistro
81
82 } // 8in clase
F&01(. 5.12 HolaMundoCliente*'ava #aciendo uso de un !estor de se!uridad.
. import )a'a.io.,;
2 import )a'a.rmi.,;
3
4 /,,
5 , Esta clase representa el o#)eto cliente para un
6 , o#)eto istri#uio e la clase 9olaMuno% $ue
7 , implementa la inter8az remota Inter8az9olaMuno.
8 , Se instala un gestor e seguria para realizar
stub downloading seguro.
9 , FautCor M. A. Aiu
10 ,/
11
12 public class "ola#undoCliente {
13
14 pu#lic static 'oi main(String argsKL) {
15 try {
16 int puertoRMI;
17 String nom#reMoo;
18 InputStreamReaer ent =
19 new InputStreamReaer(System.in);
20 Nu88ereReaer #u8= new
Nu88ereReaer(ent);
21 System.out.println(
22 +Introuce el nom#re e noo el
registro RMI-6);
23 nom#reMoo = #u8.reaAine();
24 System.out.println(
25 +Introuce el n"mero e puerto el
registro RMI-6);
26 String num*uerto = #u8.reaAine();
27 puertoRMI =
Integer.parseInt(num*uerto);
28
29 $$ arrancar un %estor de se%uridad &
esto es
30 $$ necesario si se utiliza stub
downloading
31 S'stem(setSecurit'#ana%er)ne*
R#ISecurit'#ana%er)++,
32
33 String @RARegistro =
34 +rmi-//localCost-6J num*uerto J
+/ColaMuno6;
35 // N"s$uea el o#)eto remoto y cast al
36 // o#)eto e la inter8az
37 Inter8az9olaMuno C =
38
(Inter8az9olaMuno)Maming.loo!up(@RARegistro);
39 System.out.println(+N"s$uea completa
+);
40 // in'ocar el mGtoo remoto
41 String mensa)e=C.ecir9ola());
42 System.out.println(+9olaMuno>liente- +
J mensa)e);
43 } // 8in try
44 catcC (Exception e) {
45 System.out.println(
46 +Excepci(n en 9olaMuno>liente- 6 J e);
47 }
48 } // 8in main
49 } // 8in clase
F&01(. 5.13 ,olocacin de los fic#eros 32I en una aplicacin que utiliza stub
do"nloading.
#otas al margen
P,0&!. 261
(os m*todos registrarCallback y eliminarRegistroCallback modifican una estructura
común (el objeto ector que contiene referencias a los callback de clientes". .ado que
estos m*todos se pueden invocar concurrentemente, es importante que se protejan con
e)clusin mutua. En este ejemplo la e)clusin mutua se consi!ue a trav*s del uso de un
m*todo sincronizado (s!nchronized".
P,0&!. 267
En 0ava, un /.;1#'# es un conjunto de clases, interfaces u otros paquetes relacionados y
que están declarados.
P,0&!. 268
Caching de Peb es una t*cnica que emplea la t*cnica más !eneral de caching para
evitar transferir un mismo documento repetidas veces.