Devoluciones de llamada en RMI
(Callbacks)
Sistemas Distribuidos
(Capítulo 8 de Distributed
Computing de M. L. Liu)
Devolución de llamadas, introducción
Cliente-servidor clásico
• servidor pasivo
• Tipo “pull”.
“Push/pull”, es interesante en:
• Monitorización
• Juegos
• Subastas
• Votación/encuesta
• Chat
• Tablero de noticias
• Groupware
Sistemas Distribuidos -- César Llamas Bello, 2004 2
1
Sondeo vs. Callbacks
Sondeo Callbacks
Servidor Servidor
RMI
... ...
Cliente Cliente
Sin “callbacks”, el cliente debe sondear
continuamente el servidor hasta que se produce
cierta respuesta.
Con callbacks el cliente es notificado por el servidor
Sistemas Distribuidos -- César Llamas Bello, 2004 3
Comunicaciones en dos sentidos
Algunas aplicaciones precisan que ambos
lados inicien IPCs.
Estoes posible mediante unpar de
sockets para comunicación duplex.
petición
respuesta
Proceso 1 Proceso 1
petición
respuesta
Sistemas Distribuidos -- César Llamas Bello, 2004 4
2
Callbacks RMI
El cliente inscribe un objeto remoto para recibir
una invocación remota.
• Al ocurrir cierto evento, el servidor realiza una
devolución de llamada a cada cliente interesado.
Petición RMI
Callback RMI
Servidor
Clientes
Lista de
callbacks
Sistemas Distribuidos -- César Llamas Bello, 2004 5
Interacciones C-S en los callbacks
1
2
[Link] Registro RMI
Host 3
HTTP
CiertaInterfaz_stub.class
CiertaInterfaz_stub.class
4
CiertaInterfaz_stub.class
CallbackInterfaz_stub.class
… [Link]
6 5
CallbackInterfaz_stub.class
Host del objeto cliente Host del objeto servidor
Sistemas Distribuidos -- César Llamas Bello, 2004 6
3
Despliegue
Object client host Object server host
object client directory object server directory
[Link] [Link]
[Link]
ServerImpl_Stub.class ServerImpl_Stub.class
[Link] [Link]
[Link]
ClientImpl _Stub.class ClientImpl _Stub.class
Sistemas Distribuidos -- César Llamas Bello, 2004 7
Diagrama de Clases
CallbackClientInterface
HelloInterface
UnicastRemoteObject
sayHello()
UnicastRemoteObject
HelloServer CallbackClient CallbackClientImpl
HelloImpl
listRegistry()
startRegistry()
Sistemas Distribuidos -- César Llamas Bello, 2004 8
4
Diagrama de secuencia
client registry server
rebind( )
lookup( )
sayHello()
addCallback()
notifyMe()
Sistemas Distribuidos -- César Llamas Bello, 2004 9
Interfaz de callback
El servidor ofrece un método remoto para que el
cliente registre sus callbacks
Hay que diseñar una interfaz remota para el
callback
La interfaz debe incluir un método que será
invocado en el callback desde el servidor.
El cliente deberá ser una subclase de
RemoteObject e implementará la interfaz de
callback.
El cliente se registrará frente a la clase remota
para ser rellamado (usualmente en el main).
El servidor invoca el método remoto del cliente
en caso de aparecer el evento indicado.
Sistemas Distribuidos -- César Llamas Bello, 2004 10
5
El servidor “Hola” con callbacks
UnicastRemoteObject HelloInterface
sayHello
HelloServer
RMIPort
sayHello
addCallback
Diagrama de Clases de HelloServer
Sistemas Distribuidos -- César Llamas Bello, 2004 11
El servidor “Hola” con callbacks
UnicastRemoteObject CallbackInterface
sayHello
HelloClient
RMIPort
sayHello
callMe
Diagrama de Clases de HelloClient
Sistemas Distribuidos -- César Llamas Bello, 2004 12
6
El servidor “Hola” con callbacks
HelloClient RMIregistry HelloServer
getRegistry
sayHello
addCallback
callMe
Diagrama de eventos para la aplicación Hello
Sistemas Distribuidos -- César Llamas Bello, 2004 13
Interfaz remota del servidor
import [Link].*;
/* [Link], @author M. L. Liu */
public interface CallbackServerInterface extends Remote {
// Método remoto usual
public String sayHello( ) throws [Link];
// Método de registro del callback
public void registerForCallback( CallbackClientInterface callbackClientObject )
throws [Link];
// Método de desregistro del callback
public void unregisterForCallback( CallbackClientInterface callbackClientObject )
throws [Link];
}
Sistemas Distribuidos -- César Llamas Bello, 2004 14
7
Implementación del servidor remoto
/* importaciones */
import [Link].*;
import [Link].*;
import [Link];
import [Link];
import [Link].*;
import [Link].*;
/* [Link], @author M. L. Liu */
Sistemas Distribuidos -- César Llamas Bello, 2004 15
Implementación del servidor remoto
public class CallbackServer {
public static void main(String args[ ]) {
BufferedReader br = new BufferedReader(new InputStreamReader([Link]));
String portNum, registryURL;
try{ [Link]( "Enter the RMIregistry port number:");
portNum = ([Link]()).trim();
int RMIPortNum = [Link](portNum);
startRegistry( RMIPortNum );
CallbackServerImpl exportedObj = new CallbackServerImpl();
registryURL = "rmi://localhost:" + portNum + "/callback";
[Link](registryURL, exportedObj);
[Link]("Callback Server ready.");
} catch (Exception re) { [Link]("Exception: [Link]: " + re); }
} // end main
Sistemas Distribuidos -- César Llamas Bello, 2004 16
8
Implementación del servidor remoto
// Arranca un registro RMI local si no existiera, en cierto puerto.
private static void startRegistry(int RMIPortNum) throws
RemoteException{
try {
Registry registry = [Link](RMIPortNum);
[Link]( ); // Lanza una excepción si no existe el registro
} catch (RemoteException e) {
// No hay un registro válido en el puerto.
Registry registry = [Link](RMIPortNum);
}
} // end startRegistry
} // end class callbackServer
Sistemas Distribuidos -- César Llamas Bello, 2004 17
Implementación del sirviente
import [Link].*;
import [Link].*;
import [Link];
/* [Link], @author M. L. Liu */
public class CallbackServerImpl extends UnicastRemoteObject
implements CallbackServerInterface {
private Vector clientList;
public CallbackServerImpl() throws RemoteException {
super( );
clientList = new Vector();
}
Sistemas Distribuidos -- César Llamas Bello, 2004 18
9
Implementación del sirviente
public String sayHello( ) throws [Link]
{ return("hello"); }
public synchronized void registerForCallback(
CallbackClientInterface
callbackClientObject)
throws [Link]{
if (!([Link](callbackClientObject))) {
[Link](callbackClientObject);
[Link]("Registered new client ");
doCallbacks();
} // end if
}
Sistemas Distribuidos -- César Llamas Bello, 2004 19
Implementación del sirviente
// Desregistra el cliente
public synchronized void unregisterForCallback(
CallbackClientInterface callbackClientObject)
throws [Link]{
if ([Link](callbackClientObject)) {
[Link]("Unregistered client ");
} else {
[Link](
"unregister: El cliente no estaba registrado.");
}
}
Sistemas Distribuidos -- César Llamas Bello, 2004 20
10
Implementación del sirviente
private synchronized void doCallbacks( )
throws [Link]{
[Link]( "*************\n" + "Callbacks iniciados ---");
for (int i = 0; i < [Link](); i++){
[Link]("doing "+ i +"-th callback\n");
// convert the vector object to a callback object
CallbackClientInterface nextClient =
(CallbackClientInterface)[Link](i);
// invoke the callback method
[Link]("Number of registered clients=" +
[Link]());
} // end for
[Link]("**************\n" + “Callbacks completados---");
} // doCallbacks
}// end CallbackServerImpl class
Sistemas Distribuidos -- César Llamas Bello, 2004 21
Interfaz del callback del cliente
import [Link].*;
/* [Link], @author M. L. Liu */
public interface CallbackClientInterface
extends [Link]{
// Es invocado por un callback del servidor
public String notifyMe(String message)
throws [Link];
} // end interface
Sistemas Distribuidos -- César Llamas Bello, 2004 22
11
Implementación del cliente
import [Link].*;
import [Link].*;
/* [Link], @author M. L. Liu */
public class CallbackClient {
public static void main(String args[ ]) {
try {
int RMIPort;
String hostName;
BufferedReader br = new BufferedReader( new InputStreamReader([Link]));
[Link]("Enter the RMIRegistry host namer:");
hostName = [Link]( );
[Link]("Enter the RMIregistry port number:");
String portNum = [Link]( );
RMIPort = [Link](portNum);
[Link]( "Enter how many seconds to stay registered:");
String timeDuration = [Link]( );
int time = [Link](timeDuration);
Sistemas Distribuidos -- César Llamas Bello, 2004 23
Implementación del cliente
String registryURL = "rmi://” + hostName + portNum + "/callback";
CallbackServerInterface h = (CallbackServerInterface)[Link](registryURL);
[Link]("Lookup completado\nEl servidor dijo:"+[Link]());
CallbackClientInterface callbackObj = new CallbackClientImpl();
[Link](callbackObj);
[Link]("Registered for callback.");
try { [Link](time * 1000); }
catch (InterruptedException ex){ // sleep over }
[Link](callbackObj);
[Link](“Desregistrado para callback.");
} catch (Exception e) {
[Link]( "Excepcion en CallbackClient: " + e);
} // end catch
} //end main
}//end class
Sistemas Distribuidos -- César Llamas Bello, 2004 24
12
Implementación del callback
import [Link].*;
import [Link].*;
/* CallbackClientImpl, @author M. L. Liu */
public class CallbackClientImpl extends UnicastRemoteObject
implements CallbackClientInterface {
public CallbackClientImpl() throws RemoteException { super( ); }
public String notifyMe(String message){
String returnMessage = "Call back recibido: " + message;
[Link](returnMessage);
return returnMessage;
}
}// end CallbackClientImpl class
Sistemas Distribuidos -- César Llamas Bello, 2004 25
Archivo de política
grant {
permission [Link] "*:1099", "connect, accept, resolve";
// Permite contactar con el registro de cualquier host
permission [Link] "*:1024-65535", "connect, accept, resolve";
// Permite a los clientes RMI conectar por red con los puertos públicos
// de cualquier host. Podemos poner en estos puertos el registro
permission [Link] "localhost:1099", "connect, resolve";
// Esta dirección es de un host concreto (cambiar)
permission [Link] "[Link]:1024-", "connect, accept";
permission [Link] "*:80", "connect";
// Permite conexión con el web en cualquier host
};
Sistemas Distribuidos -- César Llamas Bello, 2004 26
13