Beruflich Dokumente
Kultur Dokumente
1
CALLBACK DE CLIENTE................................................................................................................................2
INCREMENTO DE LA PARTE CLIENTE PARA CALLBACK DE CLIENTE ..................................................................3
INCREMENTO DE LA PARTE SERVIDORA PARA CALLBACK DE CLIENTE.............................................................4
PASOS PARA CONSTRUIR UNA APLICACIN RMI CON CALLBACK DE CLIENTE................................................5
STUB DOWNLOADING....................................................................................................................................7
EL GESTOR DE SEGURIDAD DE RMI........................................................................................................8
INSTANCIACIN DE UN GESTOR DE SEGURIDAD EN UN PROGRAMA RMI........................................................9
LA SINTAXIS DE UN FICHERO DE POLTICAS DE SEGURIDAD DE JAVA..............................................................9
UTILIZANDO STUB DOWNLOADING Y UN FICHERO DE POLTICAS DE SEGURIDAD.........................................10
ALGORITMOS PARA CONSTRUIR UNA APLICACIN RMI, QUE PERMITA STUB DOWNLOADING.......................11
RESUMEN........................................................................................................................................................13
EJERCICIOS....................................................................................................................................................14
REFERENCIAS...............................................................................................................................................14
RMI avanzado
En el ltimo captulo, Java RMI se describi como ejemplo de un sistema de
objetos distribuidos. En dicho captulo slo se mostraron las caractersticas de
diseo ms bsicas de RMI, aunque se mencion que el API posea un extenso
conjunto de caractersticas. El lector puede ignorar este captulo si no est
interesado en explorar de forma ms detallada RMI. Sin embargo, es muy
recomendable el uso de los gestores de seguridad (vase seccin 8.3) en todas
las aplicaciones RMI.
Este captulo analizar algunas de las caractersticas avanzadas de RMI ms
interesantes, a saber, [descarga?] stub downloading, gestores de seguridad,
y callback de cliente. Aunque no se trata de caractersticas inherentes del
paradigma de objetos distribuidos, se trata de mecanismos que pueden ser tiles
para los desarrolladores de aplicaciones. Adicionalmente, el estudio de estos
temas permite al lector reforzar su conocimiento del paradigma de objetos
distribuidos en general, y del API de RMI en particular.
Callback de cliente
Considrese una aplicacin RMI donde un objeto servidor debe notificar a los
procesos participantes la ocurrencia de algn evento. Como ejemplos, en un chat,
cuando un nuevo participante entra, se avisa al resto de los participantes de este
hecho; en un sistema de subastas en tiempo real, cuando empiezan las ofertas, se
debe avisar a los procesos participantes. Esta caracterstica tambin es til en un
juego en red cuando se informa a los jugadores de la actualizacin del estado del
juego. Dentro del entorno del API bsico bsica de RMI presentado presentada en
el captulo anterior, es imposible que el servidor inicie una llamada al cliente para
transmitirle alguna clase de informacin que est disponible, debido a que una
llamada a mtodo remoto es unidireccional (del cliente al servidor). Una forma de
}
public String notificame (String mensaje) {
String mensajeRet =Callback recibido: + mensaje;
System.out.println(mensajeRet);
return mensajeRet;
}
} // final clase ImplCallbackCliente
En este ejemplo el mtodo de callback notificame simplemente imprime la cadena
de caracteres que le pasa el servidor como argumento, y devuelve otra cadena a
dicho servidor.
Al igual que la interfaz remota de servidor, se debe utilizar el compilador rmic con
la implementacin de la interfaz remota de cliente para generar los proxies
necesarios en tiempo de ejecucin.
Incremento de la clase cliente
En la clase del objeto cliente, se necesita aadir cdigo al cliente para que
instancie un objeto de la implementacin de la interfaz remota de cliente. A
continuacin, se registra con el servidor una referencia al objeto utilizando un
mtodo remoto proporcionado por el servidor (vase la prxima seccin,
Incremento de la parte servidora para callback de cliente). Un ejemplo de cmo
debe realizarse esto se muestra a continuacin:
InterfazCallbackServidor h =
(InterfazCallbackServidor) Naming.lookup(URLRegistro);
InterfazCallbackCliente objCallback =
new ImplCallbackCliente();
// registrar el objeto para callback
h.registrarCallback(objCallback);
Las figuras entre la 8.3 hasta la 8.5 presentan el cdigo del software de la parte
cliente para la aplicacin HolaMundo modificada.
Incremento de la parte servidora para callback de cliente
En la parte del servidor, se necesita aadir un mtodo remoto para que el cliente
pueda registrarse para callback. En el caso ms sencillo, la cabecera del mtodo
puede ser anloga a la siguiente:
public void registrarCallback(
// Se puede elegir el nombre de mtodo deseado
InterfazCallbackCliente objCallbackCliente
) throws java.rmi.RemoteException;
Como argumento se pasa una referencia a un objeto que implementa la interfaz
remota de cliente (InterfazCallbackCliente, no ImplCallbackCliente). Tambin se
puede proporcionar un mtodo eliminarRegistroCallback, para que un cliente
pueda cancelar el registro (de forma que no reciba ms callbacks). La
implementacin de estos mtodos, as como la implementacin de un mtodo
local hacerCallbacks para realizar los callbacks se muestra en la figura 8.7. La
figura 8.6 muestra el fichero con la interfaz del servidor aumentado con las
cabeceras de los mtodos adicionales. La figura 8.8 muestra el cdigo para el
objeto servidor, que queda sin modificar respecto a la anterior versin, presentada
en el captulo anterior.
El servidor necesita emplear una estructura de datos que mantenga una lista de
las referencias a la interfaz de cliente registradas para callbacks. En el cdigo de
ejemplo, un objeto Vector es utilizado para este propsito, aunque se puede
sustituir por cualquier otra estructura de datos apropiada. Cada llamada a
registrarCallback implica aadir 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 mtodo hacerCallbacks)
siempre que se realiza lleva a cabo una llamada a registrarCallback, donde se
enva al cliente a travs de callback, el nmero de clientes actualmente
registrados. En otras aplicaciones, los callbacks se pueden activar por otros
eventos y pueden gestionarse a travs de un manejador de eventos.
En el ejemplo, un cliente elimina su registro despus de un determinado periodo
de tiempo. En las aplicaciones reales, la cancelacin del registro 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).
Pasos para construir una aplicacin RMI con callback de cliente
En las siguientes pginas se presenta una descripcin revisada del procedimiento
para construir una aplicacin RMI paso a paso, permitiendo callback de cliente.
Algoritmo para desarrollar el software de la parte del servidor
1. Crear un directorio donde se almacenen todos los ficheros generados por la
aplicacin.
2. Especificar la interfaz remota de servidor en InterfazCallbackServidor.java.
Compilarla y revisarla hasta que no exista ningn error de sintaxis.
3. Implementar la interfaz en ImplCallbackServidor.java. Compilarlo y revisarlo
hasta que no exista ningn error de sintaxis.
4. Utilizar el compilador RMI rmic para procesar la clase de la implementacin y
generar los ficheros stub y skeleton para el objeto remoto:
rmic ImplCallbackServidor
Los ficheros generados se pueden encontrar en el directorio como
ImplCallbackServidor_Skel.class y ImplCallbackServidor_Stub.class. Los pasos
3 y 4 deben repetirse cada vez que se cambie la implementacin de la interfaz.
5. Obtener una copia del fichero class de la interfaz remota del cliente.
Alternativamente, obtener una copia del fichero fuente para la interfaz remota y
compilarlo utilizando javac para generar el fichero class de la interfaz
InterfazCallbackCliente.class.
6. Crear el programa correspondiente al objeto servidor ServidorEjemplo.java.
Compilarlo y revisarlo hasta que no exista ningn error de sintaxis.
7. Obtener una copia del fichero stub de la interfaz remota del cliente
ImplCallbackCliente_Stub.class.
8. Activar el objeto servidor
java ServidorEjemplo
Algoritmo para desarrollar el software de la parte cliente
1. Crear un directorio donde se almacenen todos los ficheros generados por la
aplicacin.
2. Especificar la interfaz remota de cliente en InterfazCallbackCliente.java.
Compilarla y revisarla hasta que no exista ningn error de sintaxis.
3. Implementar la interfaz en ImplCallbackCliente.java. Compilarlo y revisarlo
hasta que no exista ningn error de sintaxis.
4. Utilizar el compilador RMI rmic para procesar la clase de la implementacin
ImplCallbackCliente.class y generar los ficheros stub y skeleton
ImplCallbackCliente_Skel.class y ImplCallbackCliente_Stub.class para el objeto
remoto:
rmic ImplCallbackCliente
Los ficheros generados se pueden encontrar en el directorio como
ImplCallbackCliente_Skel.class y ImplCallbackCliente_Stub.class. Los pasos 3
y 4 deben repetirse cada vez que se cambie la implementacin de la interfaz.
5. Obtener una copia del fichero class de la interfaz remota del servidor.
Alternativamente, obtener una copia del fichero fuente para la interfaz remota y
compilarlo utilizando javac para generar el fichero class de la interfaz Interfaz.
6. Crear el programa correspondiente al objeto cliente ClienteEjemplo.java.
Compilarlo y revisarlo hasta que no exista ningn error de sintaxis.
7. Obtener una copia del fichero stub de la interfaz remota del servidor
ImplCallbackServidor_Stub.class.
8. Activar el objeto cliente
java ClienteEjemplo
La figura 8.9 muestra los ficheros que se necesitan en los dos extremos, cliente y
servidor, cuando se utiliza callback de cliente. (Como se mencion en el captulo
anterior, desde la versin 1.2 de Java no se requieren clases skeleton en las
aplicaciones RMI. Las funciones de las clases skeleton se realizan a travs de una
tcnica denominada reflexin.)
Stub downloading
En la arquitectura de un sistema de objetos distribuidos se requiere un proxy para
interactuar con la llamada a un mtodo remoto de un objeto cliente. En Java RMI,
este proxy o intermediario es el stub de la interfaz remota del servidor. En el
captulo anterior se describieron la forma en la que se generan los proxies de la
interfaz remota del servidor (ambos el stub y el skeleton) mediante el compilador
RMI rmic. La clase stub generada debe estar en el nodo cliente en tiempo de
ejecucin cuando un programa cliente se ejecute. Esto se puede resolver
Estos dos mandatos asumen que el fichero de polticas se llama java.policy y est
disponible en el directorio actual de la parte servidora y cliente.
Una descripcin detallada de las polticas de seguridad Java, incluyendo una
explicacin de la sintaxis utilizada en este fichero, se puede encontrar en
[java.sun.com/marketing, 4].
Utilizando Uso de stub downloading y un fichero de polticas de seguridad
1. Si debe descargarse el stub de un servidor HTTP, transferir transfiera la clase
stub a un directorio apropiado del servidor HTTP, por ejemplo, el al directorio
stubs del nodo www.miempresa.com, y asegurarse asegrese de que el
permiso de acceso del fichero es de lectura para todos los usuarios.
2. Cuando se activa el servidor, se debe especificar las siguientes opciones del
mandato:
java Djava.rmi.server.codbase=<URL>
-Djava.security.policy=
<ruta completa del fichero de polticas de seguridad>
donde
<URL> es el URL del directorio donde se encuentra la clase stub; por ejemplo,
http://www.miempresa.com/stubs/.
Obsrvese la barra del final del URL, que indica que el URL especifica un
directorio, no un fichero.
<ruta completa del fichero de polticas de seguridad> especifica el fichero de
polticas de seguridad de la aplicacin; por ejemplo, java.security, si el fichero
java.security se encuentra en el directorio actual.
Por ejemplo,
java
Djava.rmi.server.codebase=http://www.miempresa.com/stubs/
-Djava.security.policy=java.security HolaMundoServidor
(todo en una lnea)
arrancar la aplicacin HolaMundoServidor y permitir realizar stub downloading
del directorio stubs del servidor Web web de www.miempresa.com.
La figura 8.13 muestra el conjunto de ficheros que se necesitan para una
aplicacin RMI y donde se deben colocar, suponiendo stub downloading dinmico.
(Por simplicidad, se asume que la aplicacin no usa callback de cliente. Se
podran aadir los ficheros necesarios para realizar callback de cliente, si se
desear.)
En la parte del servidor, los ficheros necesarios son los ficheros class del servidor,
la interfaz remota, la implementacin de la interfaz (generada por javac), el fichero
class del stub (generado por rmic), la clase del skeleton (generado por rmic), y el
Resumen
En este captulo se han analizado algunas de las caractersticas avanzadas del
API de Java RMI. Aunque estas caractersticas no son parte inherente del
paradigma de objetos distribuidos, son interesantes y tiles para algunas
aplicaciones.
Callback de cliente
El callback de cliente es til para las aplicaciones que deseen que el servidor
les notifique la ocurrencia de algn evento.
El callback de cliente permite que un objeto servidor realice una invocacin de
mtodo remoto de un cliente a travs de la referencia a una interfaz remota de
dicho cliente.
Para dotar a la aplicacin de callback de cliente, el software de la parte cliente
debe proporcionar una interfaz remota, instanciar un objeto que implemente
dicha interfaz y pasar la referencia del objeto al servidor. El objeto servidor
guarda estas referencias del cliente en una estructura de datos. Cuando el
evento esperado ocurre, el objeto servidor invoca un mtodo 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.
Stub downloading y gestor de seguridad
La caracterstica de stub downloading permite que un cliente pueda cargar una
clase stub en tiempo de ejecucin.
Stub downloading requiere la configuracin de la propiedad
java.rmi.server.codebase cuando se inicia el servidor: esta propiedad debe
configurarse con el directorio de un servidor HTTP donde se encuentre
almacenada la copia del fichero class del stub y accesible a todos los usuarios.
Stub downloading requiere la instalacin de un gestor de seguridad RMI tanto
en la parte cliente como en la servidora.
Para llevar a cabo stub downloading, es necesario el uso de un gestor de
seguridad, ya que la ejecucin de un objeto descargado de una mquina
desconocida puede suponer una amenaza para el computador cliente.
Un gestor de seguridad lleva a cabo las restricciones especificadas en un
fichero de polticas de seguridad de Java, que puede ser el fichero de polticas
del sistema o un fichero de polticas aplicado solamente a una aplicacin
individual.
En este captulo se mostr un ejemplo de fichero de polticas de seguridad
para aplicaciones RMI.
Por cuestiones de seguridad, el uso de los gestores de seguridad es
recomendable en todas las aplicaciones RMI, independientemente de que
utilicen stub downloading o no.
Referencias
1. Descarga dinmica de cdigo utilizando RMI,
http://java.sun.com/products/jdk/1.2/docs/guide/rmi/codebase.html
2. Introduccin a la computacin distribuida con RMI,
http://developer.java.sun.com/developer/onlineTraining/rmi/RMI.html
3. CERT Coordination Center, CERT/CC Computer Virus Resources,
http://www.cert.org/other_sources/viruses.html
4. Java Remote Method Invocation Computacin distribuida para Java,
http://java.sun.com/marketing/collateral/javarmi.html
Figuras
Figura 8.1 Sondeo (polling) frente a callback.
import java.rmi.*;
/**
* Esto es una interfaz remota para ilustrar el
* callback de cliente.
* @author M. L. Liu
*/
public interface InterfazCallbackCliente
extends java.rmi.Remote{
// Este mtodo remoto se invoca mediante callback
// de servidor, de forma que realiza un callback a
// un cliente que implementa esta interfaz.
// @message una cadena de caracteres que contiene
// informacin procesada por el cliente.
public void notificame(String mensaje)
throws java.rmi.RemoteException;
} // fin interfaz
import java.rmi.*;
import java.rmi.server.*;
/**
* Esta clase implementa la interfaz remota
* InterfazCallbackCliente.
* @author M. L. Liu
*/
public class ImplCallbackCliente extends
UnicastRemoteObject
implements InterfazCallbackCliente {
public ImplCallbackCliente () throws
RemoteException {
super( );
}
public String notificame(String mensaje){
18
19
20
21
22
23
System.out.println(mensajeRet);
return mensajeRet;
}
} // fin clase ImplCallbackCliente
import java.io.*;
import java.rmi.*;
/**
* Esta clase representa el objeto cliente para un
* objeto distribuido de la clase ImplCallbackServidor,
* que implementa la interfaz remota
* InterfazCallbackServidor. Tambin acepta callbacks
* del servidor.
*
*
*
* @author M. L. Liu
*/
public class ClienteEjemplo {
public static void main(String args[]) {
try {
int puertoRMI;
String nombreNodo;
InputStreamReader ent =
new InputStreamReader(System.in);
BufferedReader buf= new BufferedReader(ent);
System.out.println(
Introduce el nombre de nodo del registro
RMI:);
nombreNodo = buf.readLine();
System.out.println(
Introduce el nmero de puerto del
registro RMI:);
String numPuerto = buf.readLine();
puertoRMI = Integer.parseInt(numPuerto);
System.out.println(
Introduce cuantos segundos va a
permanecer registrado:);
String duracionTiempo = buf.readLine();
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
import java.rmi.*;
/**
* Esto es una interfaz remota para ilustrar el
* callback de cliente.
* @author M. L. Liu
*/
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import java.rmi.*;
import java.rmi.server.*;
import java.util.Vector;
/**
* Esta clase implementa la interfaz remota
* InterfazCallbackServidor.
* @author M. L. Liu
*/
public class ImplCallbackServidor extends
UnicastRemoteObject
implements InterfazCallbackServidor {
private Vector listaClientes;
public ImplCallbackServidor () throws
RemoteException {
super( );
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
listaClientes.addElement(objCallbackCliente);
System.out.println(Nuevo cliente
registrado );
hacerCallbacks();
} // fin if
}
// Este mtodo remoto permite a un objeto cliente
// cancelar su registro para callback
// @param id es un identificador para el cliente;
// el servidor lo utiliza nicamente para
identificar al cliente registrado.
public synchronized void eliminarRegistroCallback(
InterfazCallbackCliente objCallbackCliente)
throws java.rmi.RemoteException{
if
(listaClientes.removeElement(objCallbackCliente)){
System.out.println(Cliente no registrado
);
} else {
System.out.println(
eliminarRegistro: el cliente no fue
registrado.
}
}
private synchronized void hacerCallbacks( ) throws
java.rmi.RemoteException {
// realizar callback de un cliente registrado
System.out.println(
**************************************\n +
Callback iniciado - );
58
59
60
61
62
63
64
65
66
67
68
69
70
71
import
import
import
import
import
import
java.rmi.*;
java.rmi.server.*;
java.rmi.registry.Registry;
java.rmi.registry.LocateRegistry;
java.net.*;
java.io.*;
/**
* Esta clase representa el objeto servidor para un
* objeto distribuido de la clase Callback, que
implementa la interfaz remota InterfazCallback.
* @author M. L. Liu
*/
public class ServidorEjemplo {
public static void main(String args[]) {
InputStreamReader ent =
new InputStreamReader(System.in);
BufferedReader buf= new BufferedReader(ent);
String numPuerto, URLRegistro;
try {
System.out.println(
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
Figura 8.9 Colocacin de los ficheros en una aplicacin RMI con callback de
cliente.
import
import
import
import
import
import
java.rmi.*;
java.rmi.server.*;
java.rmi.registry.Registry;
java.rmi.registry.LocateRegistry;
java.net.*;
java.io.*;
/**
* Esta clase representa el objeto servidor para un
* objeto distribuido de la clase HolaMundo, que
implementa la interfaz remota InterfazHolaMundo. Se
instala un gestor de seguridad para realizar stub
downloading seguro.
* @author M. L. Liu
*/
public class HolaMundoServidor {
public static void main(String args[]) {
InputStreamReader ent =
new InputStreamReader(System.in);
BufferedReader buf= new BufferedReader(ent);
String numPuerto, URLRegistro;
try {
System.out.println(
Introducir el nmero de puerto del
registro RMI:);
numPuerto=(buf.readLine()).trim();
int numPuertoRMI =
Integer.parseInt(numPuerto);
27
28
29
30
31
32
33
34
35
36
System.setSecurityManager(
new RMISecurityManager());
arrancarRegistro(numPuertoRMI);
ImplHolaMundo objExportado = new
ImplHolaMundo();
URLRegistro =
rmi://localhost: + numPuerto +
/holaMundo;
37
38
39
Naming.rebind(URLRegistro, objExportado);
System.out.println(
Servidor registrado. El registro
contiene:);
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
listarRegistro(URLRegistro);
System.out.println(Servidor Hola Mundo
preparado.);
} // fin try
catch (Exception exc) {
System.out.println(
Excepcin en HolaMundoServidor.main: +
exc);
} // fin catch
} // fin main
// Este mtodo arranca un registro RMI en el nodo
// local, si no existe en el nmero de puerto
especificado.
private static void arrancarRegistro(int
numPuertoRMI)
throws RemoteException {
try {
Registry registro =
LocateRegistry.getRegistry(numPuertoRMI);
registro.list(); // Esta llamada lanza
// una excepcin si el registro no existe
}
catch (RemoteException e) {
// No existe registro vlido en el puerto
System.out.println(
El registro RMI no se localiza en este
puerto
+ numPuertoRMI);
Registry registro =
LocateRegistry.createRegistry(numPuertoRMI);
System.out.println(
Registro RMI creado en el puerto +
numPuertoRMI);
}
} // fin arrancarRegistro
// Este mtodo lista los nombres registrados en RMI
private static void listarRegistro(String
URLRegistro)
74
75
76
77
78
79
80
81
82
System.out.println(
Registro + URLRegistro + contiene: );
String [] nombres = Naming.list(URLRegistro);
for (int i=0; i< nombres.length; i++)
System.out.println(nombres[i]);
} // fin listarRegistro
} // fin clase
import java.io.*;
import java.rmi.*;
/**
* Esta clase representa el objeto cliente para un
* objeto distribuido de la clase HolaMundo, que
* implementa la interfaz remota InterfazHolaMundo.
* Se instala un gestor de seguridad para realizar stub
downloading seguro.
* @author M. L. Liu
*/
public class HolaMundoCliente {
public static void main(String args[]) {
try {
int puertoRMI;
String nombreNodo;
InputStreamReader ent =
new InputStreamReader(System.in);
BufferedReader buf= new
BufferedReader(ent);
System.out.println(
Introduce el nombre de nodo del registro
RMI:);
nombreNodo = buf.readLine();
System.out.println(
Introduce el nmero de puerto del
registro RMI:);
String numPuerto = buf.readLine();
puertoRMI = Integer.parseInt(numPuerto);
// arrancar un gestor de seguridad esto
es
30
31
System.setSecurityManager(new
RMISecurityManager());
32
33
34
String URLRegistro =
rmi://localhost:+ numPuerto +
/holaMundo;
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
Figura 8.13 Colocacin de los ficheros RMI en una aplicacin que utiliza stub
downloading.
Notas al margen
Pgina 241
Los mtodos registrarCallback y eliminarRegistroCallback modifican una
estructura comn (el objeto Vector que contiene referencias a los callback de
clientes). Dado que estos mtodos se pueden invocar concurrentemente, es
importante que se protejan con exclusin mutua. En este ejemplo la exclusin
mutua se consigue a travs del uso de un mtodo sincronizado (synchronized).
Pgina 245
En Java, un paquete es un conjunto de clases, interfaces u otros paquetes
relacionados y que estn declarados.
Pgina 246
Caching de Web es una tcnica que emplea la tcnica ms general de caching
para evitar transferir un mismo documento repetidas veces.