Download SOD-Tema3-Comunicaciones (Parte-2)

Document related concepts
no text concepts found
Transcript
r
in
a
lim
Apuntes de Sistemas Operativos Distribuidos
Pr
e
Autor: Fabio E. Rivalta / Carlos Neetzel
Material: dictado de clases
Tema: Comunicación entre procesos (Parte 2)
Fecha: 05/2007
Ve
r
si
ón
Bibliografía utilizada:
• Apuntes de sistemas operativos distribuidos - Carlos Neetzel
• Trabajos de Sistemas Operativos II U. Morón 2006
• Apuntes de Internet
Ve
r
si
ón
Pr
e
lim
RPC
in
a
r
RPC: Generalidades
lim
in
a
r
Paradigma procedimental.
Proporciona la comunicación lógica entre el cliente y el servidor.
No requiere conocimiento de la red.
Pretende hacerle parecer al programador que está llamando a una rutina local.
Proceso del Cliente
(10)
ón
procedimiento local = (1)
Esquema
Pr
e
Cliente
llamada del sistema = (2)
Servidor
(6)
(5)
(7)
(9)
(4)
(8)
Funciones de
Red
Kernel Local
Proceso del Servidor
Stub del Servidor
si
Stub del Cliente
Ve
r
•
•
•
•
Funciones de
Red
comunicación de red = (3)
Kernel Remoto
RPC: Sobre los parámetros
in
a
r
Por valor
Por referencia
Copia/restauración
ón
si
•
Número de programa.
Número de la versión.
Número de los procedimientos.
El archivo /etc/rpc enumera algunos programas RPC.
El comando rpcinfo enumera los programas RPC registrados y sus números de
versión correspondientes.
El administrador RPC de Sun tiene una lista de los programas que han sido
registrados con ellos.
Ve
r
•
•
•
•
•
Pr
e
RPC: Versiones de un programa
lim
•
•
•
Cliente
ón
Pr
e
in
a
lim
Portmap comienza automáticamente.
Inicialización.
Encontrar el puerto de un programa remoto.
Programa remoto ya registrado.
Asignación de Puertos.
Comunicación del cliente.
Servidor
Programa
Cliente
si
2
Ve
r
•
•
•
•
•
•
r
RPC: Determinar el número de puerto destino con portmap
3
111
Portmap
123
4
Programa
Servidor
1
RPC: Conseguir la información del registro RPC con Rpcinfo
r
in
a
lim
Pr
e
ón
si
•
Rpcinfo brinda la información actual del registro RPC al portmap.
Se puede utilizar para eliminar registros.
Puede encontrar los servicios RPC registrados y brindar sus números de puerto y
los transportes utilizados.
Puede llamar a una versión de un programa usando el transporte TCP o UDP, y
reportar si la respuesta fue recibida.
Ve
r
•
•
•
RPC: Independencia del protocolo de transporte
r
lim
•
Soporta TCP y UDP como protocolo.
No implementa ningún tipo de confiabilidad.
Se debe utilizar política de retransmisión y de timeout si utiliza un medio no confiable
(UDP)
Deduce la información de los procedimientos remotos o su ejecución, del protocolo
subyacente.
in
a
•
•
•
Pr
e
Transporte UDP
• Los procedimientos son idempotentes.
• El tamaño de los argumentos y de los resultados debe ser menor a 8 kbytes.
• El servidor maneja varios cientos de clientes.
Ve
r
si
ón
Transporte TCP
• Se necesita un transporte confiable.
• Los procedimientos son no-idempotentes.
• El tamaño de los argumentos o de los resultados excede los 8 Kbytes.
RPC: Características
lim
in
a
r
Problemas
• El cliente no puede localizar el servidor.
• Se pierde el mensaje de solicitud del cliente al servidor.
• Se pierde el mensaje de respuesta del servidor al cliente.
• Fallas en el servidor
• El cliente envía una solicitud y falla antes de recibir la respuesta.
Pr
e
Ventajas
• Por ser el primer tipo de middleware es el menos complicado de usar y comprender
• Por ser sincrónico, provee mayor integridad de datos
si
ón
Desventajas
• Exige alto nivel de procesamiento
• Tiene bajo rendimiento
Ve
r
Dificultades
• Obliga a utilizar el mismo lenguaje en ambos lados
• Dependiente de la plataforma
• Poco escalable
• Diseño funcional de servicios, no orientado a objetos
• No confiable al poder utilizar un protocolo de transporte como UDP
Ve
r
si
ón
Pr
e
lim
in
a
r
RPC: Código de un servidor
Ve
r
si
ón
in
a
lim
Pr
e
out * sumar_1_svc(in *argp, struct svc_req *rqstp)
{
static out result;
printf("tamano de out %d\n", sizeof(out));
printf("Mensaje recibido de %s\n", argp->msg);
result.rpta = argp->a + argp->b;
strcpy(result.status,"OK");
return(&result);
}
r
#include "calc.h"
RPC: Código del cliente
Ve
r
si
ón
Pr
e
lim
in
a
r
#include "calc.h"
void calcprg_1( char* host )
{
CLIENT *clnt;
out *result_1;
in sumar_1_arg;
clnt = clnt_create(host, CALCPRG, CALCVER, "udp");
if (clnt == NULL) {
clnt_pcreateerror(host);
exit(1);
}
result_1 = sumar_1(&sumar_1_arg, clnt);
if (result_1 == NULL) {
clnt_perror(clnt, "call failed:");
}
else
printf("%s: valor de (a+b) = %d\n", result_1->status, result_1->rpta);
clnt_destroy(clnt);
}
main( int argc, char* argv[] )
{
char *host;
if(argc < 2) {
printf("usage: %s server_host\n", argv[0]);
exit(1);
}
host = argv[1];
calcprg_1( host );
}
Pr
e
in
a
lim
#include <memory.h>
#include "calc.h"
static struct timeval TIMEOUT = { 25, 0 };
out *
sumar_1(in *argp, CLIENT *clnt)
{
static out clnt_res;
r
RPC: Stub del cliente
Llamada al procedimiento que
esta asociado a un manejador
especifico del cliente.
(Envio del mensaje al servidor)
}
Ve
r
si
ón
memset((char *)&clnt_res, 0, sizeof(clnt_res));
if (clnt_call(clnt, sumar, (xdrproc_t) xdr_in, argp, (xdrproc_t) xdr_out,
&clnt_res, TIMEOUT) != RPC_SUCCESS) {
return (NULL);
}
return (&clnt_res);
Pr
e
lim
in
a
#include "calc.h"
#include <stdio.h>
#include <stdlib.h>/* getenv, exit */
#include <rpc/pmap_clnt.h> /* for pmap_unset */
#include <string.h> /* strcmp */
#include <memory.h>
#include <sys/socket.h>
#include <netinet/in.h>
#ifdef __STDC__
#define SIG_PF void(*)(int)
#endif
r
RPC: Stub del servidor
Ve
r
si
ón
static void
calcprg_1(struct svc_req *rqstp, register SVCXPRT *transp)
{
union {
in sumar_1_arg;
} argument;
in
a
char *result;
xdrproc_t xdr_argument, xdr_result;
char *(*local)(char *, struct svc_req *);
r
RPC: Stub del servidor (Cont)
Ve
r
si
ón
Pr
e
lim
switch (rqstp->rq_proc) {
case NULLPROC:
(void) svc_sendreply(transp, (xdrproc_t) xdr_void, (char *)NULL);
return;
case sumar:
xdr_argument = (xdrproc_t) xdr_in;
xdr_result = (xdrproc_t) xdr_out;
local = (char *(*)(char *, struct svc_req *)) sumar_1_svc;
break;
default:
svcerr_noproc(transp);
return;
}
RPC: Stub del servidor (Cont)
Ve
r
si
ón
Pr
e
lim
in
a
r
int main(int argc, char **argv)
{ register SVCXPRT *transp;
(void) pmap_unset(CALCPRG, CALCVER);
transp = svcudp_create(RPC_ANYSOCK);
if (transp == NULL) {
fprintf(stderr, "cannot create udp service.");
exit(1);
}
if (!svc_register(transp, CALCPRG, CALCVER, calcprg_1,
IPPROTO_UDP)) {
fprintf(stderr, "unable to register (CALCPRG, CALCVER, udp).");
exit(1);
}
transp = svctcp_create(RPC_ANYSOCK, 0, 0);
if (transp == NULL) {
fprintf(stderr, "cannot create tcp service.");
exit(1);
}
if (!svc_register(transp, CALCPRG, CALCVER, calcprg_1,
IPPROTO_TCP)) {
fprintf(stderr, "unable to register (CALCPRG, CALCVER, tcp).");
exit(1);
}
RPC: Stub del servidor (Cont)
in
a
r
svc_run();
fprintf(stderr, "svc_run returned");
exit(1);
}
}
Ve
r
si
ón
Pr
e
lim
(void) memset((char *)&argument, 0, sizeof (argument));
if (!svc_getargs(transp, xdr_argument, (caddr_t) &argument)) {
svcerr_decode(transp);
return;
}
result = (*local)((char *)&argument, rqstp);
if (result != NULL && !svc_sendreply(transp, xdr_result, result)) {
svcerr_systemerr(transp);
}
if (!svc_freeargs(transp, xdr_argument, (caddr_t) &argument)) {
fprintf(stderr, "unable to free arguments");
exit(1);
}
return;
Ve
r
si
ón
Pr
e
lim
CORBA
in
a
r
Ve
r
si
ón
in
a
lim
Pr
e
1.Definir los objetos del servidor
mediante IDL.
2.Cargar la información de IDL en el
InterfaceRepository
3.Pre-compilar el IDL para generar
stubsy esqueletos.
4.Escribir el código del servidor,
heredando de los esqueletos (y
siguiendo el ejemplo)
5.Compilar los archivos servidores.
6.Registrar los objetos en tiempo de
ejecución en el
ImplementationRepository
7.Instanciaciónde los sirvientes (por el
adaptador, normalmente bajo
demanda)
8.Escribir el código del cliente, (incluye
los stubsgenerados)
9.Compilar el cliente
10.Ejecutar servidor, luego cliente.
r
CORBA: Proceso de desarrollo
CORBA: IDL (Interface Definition Language)
in
a
r
Es el lenguaje mediante el cuál se describen los métodos que un determinado objeto
del entorno proporciona al resto de elementos del mismo.
Pr
e
interface Cuenta
{
void ingresar(in long cantidad);
void retirar(in long cantidad);
long balance();
};
lim
Ejemplo:
Ve
r
si
ón
Language Mappings:
Traducen la definición IDL a un lenguaje de programación como:
• C++,
• Ada,
• COBOL,
• SmallTalk,
• Java
Este proceso genera dos fragmentos de código denominados Stub y Skeleton que
representan el código de cliente y servidor respectivamente.
CORBA: IDL (Cont)
Test.IDL
El código cliente generado en
base a la definición IDL (stub)
contiene las llamadas para
realizar el proceso de
marshalling.
in
a
r
interface Cuenta
{
void ingresar (in long cantidad);
};
Compilador IDL
lim
Marshalling: Traducción de los
argumentos a un formato
intermedio y pedir al ORB su
ejecución.
Test_Skel.c++
Ve
r
si
ón
class Cuenta_Stub : ...
{
void ingresar(CORBA::Long &cantidad)
{ <MARSHALLING> }
}
Pr
e
Test_Stub.c++
class Test_Skel : ...
{
virtual
void ingresar(CORBA::Long &cantidad)=0;
void __ingresar()
{
<DE-MARSHALLING>
ingresar(c);
}
}
El código servidor generado en base a la definición
IDL (skeleton) contiene las
llamadas para realizar el proceso inverso
(demarshalling).
De-marshalling: Recuperar del ORB los parámetros
con los que se invocó el método, construir la
llamada y realizar la petición.
CORBA: Componentes de un ORB
lim
Código servidor asociado al objeto. Representa el
elemento análogo al stub del cliente.
Se encarga de simular la petición remota del cliente
como una petición local a la implementación real
del objeto.
si
ón
Pr
e
Código cliente asociado al objeto remoto con
el que se desea interactuar.
Simula para el cliente los métodos del objeto
remoto, asociando a cada uno de los
métodos una serie de funciones que realizan
la comunicación con el objeto servidor.
in
a
r
La arquitectura completa de comunicaciones de CORBA es la siguiente:
Skeleton:
Stub:
DSI: (Dynamic Skeleton Interface)
Alternativa al uso de stubs estáticos
que permite que un cliente solicite
peticiones a servidores cuyos
interfaces se desconocían en fase de
compilación.
Alternativa dinámica al uso de skeletons estáticos
definidos en tiempo de compilación del objeto.
Es usado por servidores que durante su ejecución
pueden arrancar diferentes objetos que pueden ser
desconocidos cuando se compiló el servidor.
Ve
r
DII: (Dynamic Invocation Interface)
CORBA: Componentes de un ORB (Cont)
Ve
r
si
ón
Pr
e
lim
in
a
r
ORB/Interface ORB:
• Elemento encargado de (entre otras) las tareas asociadas a la interconexión
entre la computadora cliente y servidor, de forma independiente de las
arquitecturas hardware y SO.
• Debido a que tanto clientes como servidores pueden requerir de ciertas
funcionalidades del ORB, ambos son capaces de acceder a las mismas por
medio de una interfase.
Las dos principales responsabilidades del ORB son:
• Localización de objetos: El cliente desconoce la computadora donde se
encuentra el objeto remoto.
• Comunicación entre cliente y servidor: De forma independiente de protocolos de
comunicación o características de implementación (lenguaje, sistema operativo,
...)
Adaptador de Objetos:
• En este elemento se registran todos los objetos que sirven en un determinado
nodo. Es el encargado de mantener todas las referencias de los objetos que
sirven en una determinada computadora de forma que cuando llega una
petición a un método es capaz de redirigirla al código del skeleton adecuado.
Existen dos tipos de Adaptadores de Objetos especificados por OMG:
• BOA: (Basic Object Adapter).
• POA: (Portable Object Adapter).
Pr
e
lim
in
a
r
CORBA: Forma de comunicación
Ve
r
si
ón
1. El cliente invoca el método asociado en el stub que realiza el proceso de marshalling. (Stub
cliente)
2. El stub solicita del ORB la transmisión de la petición hacia el objeto servidor. (ORB cliente)
3. El ORB del servidor toma la petición y la transmite el Adaptador de Objetos asociado, por lo
general sólo hay uno. (ORB servidor)
4. El Adaptador de Objetos resuelve cuál es el objeto invocado, y dentro de dicho objeto cuál
es el método solicitado (Adaptador de Objetos)
5. El skeleton del servidor realiza el proceso de de-marshalling de los argumentos e invoca a
la implementación del objeto. (Skeleton servidor)
6. La implementación del objeto se ejecuta y los resultados y/o parámetros de salida se
retornan al skeleton. (Implementación del objeto)
7. El proceso de retorno de los resultados es análogo.
CORBA: Ejemplo - IDL
in
a
r
interface Callback
{
void reply (in string msg);
lim
};
Ve
r
si
ón
Pr
e
interface Sender
{
void message (in Callback obj, in string msg);
};
CORBA: Ejemplo - Servidor
r
using namespace std;
in
a
CORBA::ORB_ptr orb = CORBA::ORB::_nil();
CORBA::String_var mess; // = CORBA::String::_nil();
Callback_ptr callback = Callback::_nil();
Ve
r
si
ón
Pr
e
lim
class Worker : public MICOMT::Thread
{ public: void _run(void*)
{ for (;;)
{ cout << "sending reply ``" << mess << "'' to the client." << endl;
callback->reply(mess);
#ifndef _WIN32
sleep(1);
#else // _WIN32
_sleep(1);
#endif // _WIN32
}
}
};
// Implementacion de la interfase Sender
class Sender_impl : virtual public POA_Sender
{
public: void message(Callback_ptr obj, const char* msg)
{
cout << "client send message ``" << msg << "''" << endl;
callback = Callback::_duplicate(obj);
mess = msg;
Worker* worker = new Worker();
worker->start();
}
};
lim
in
a
Int main(int argc, char* argv[])
{
orb = CORBA::ORB_init(argc, argv, "mico-local-orb");
CORBA::Object_ptr obj = orb->resolve_initial_references("RootPOA");
PortableServer::POA_ptr poa = PortableServer::POA::_narrow(obj);
assert(!CORBA::is_nil(poa));
r
CORBA: Ejemplo - Servidor (Cont)
Sender_impl* servant = new Sender_impl;
PortableServer::ObjectId_var id = poa->activate_object(servant);
Ve
r
}
si
CORBA::release(manager);
CORBA::release(poa);
CORBA::release(orb);
ón
cout << "server started." << endl;
orb->run();
Pr
e
PortableServer::POAManager_ptr manager = poa->the_POAManager();
manager->activate();
CORBA: Ejemplo - Cliente
in
a
ón
Pr
e
class ORBThread : virtual public MICOMT::Thread
{
public: void _run(void*)
{
orb->run();
}
};
lim
CORBA::ORB_ptr orb = CORBA::ORB::_nil();
class Callback_impl: virtual public POA_Callback
{
public: void reply(const char* msg)
{
cout << "got: " << msg << endl;
}
};
r
using namespace std;
si
Int main(int argc, char* argv[])
{ //iniciar el ORB
// :: significa namespace
orb = CORBA::ORB_init(argc, argv, "mico-local-orb");
Ve
r
//Localizar el naming Service y obtener ref a el
CORBA::Object_ptr o = orb->resolve_initial_references("RootPOA");
PortableServer::POA_ptr poa = PortableServer::POA::_narrow(o);
assert(!CORBA::is_nil(poa));
Callback_impl* servant = new Callback_impl;
poa->activate_object(servant);
CORBA: Ejemplo - Cliente (Cont)
in
a
r
CORBA::Object_ptr obj = poa->servant_to_reference(servant);
Callback_ptr callback = Callback::_narrow(obj);
lim
PortableServer::POAManager_ptr manager = poa->the_POAManager();
manager->activate();
CORBA::release(manager);
Pr
e
// Crear e iniciar un nuevo Thread en el cual se ejecutará para recibir peticiones al objeto Callback
ORBThread* main = new ORBThread;
main->start();
ón
CORBA::Object_ptr obj2 = orb->bind("IDL:Sender:1.0");
Sender_ptr sender = Sender::_narrow(obj2);
assert(!CORBA::is_nil(sender));
CORBA::String_var msg = "Hello";
cout << "sending message ``" << msg << "'' to the server." << endl;
sender->message(callback, msg);
Ve
r
si
for (;;)
{
// we can do something in the infinite loop
#ifndef _WIN32
sleep(1);
#else // _WIN32
sleep(1);
#endif // _WIN32
}
// or we can use main->wait() for waiting on main thread finish
return 0;
}
Ve
r
si
ón
Pr
e
lim
RMI
in
a
r
RMI: Introducción
in
a
r
El soporte para RMI en Java está basado en las interfases y clases definidas en los
paquetes:
• java.rmi
• java.rmi.server
Ve
r
si
ón
Pr
e
lim
Características de Java RMI:
• Paso de parámetros a métodos remotos:
• Por valor: copia secuenciada del objeto en el flujo de salida (se envía el
objeto)
• Tipos primitivos (serializables)
• Objetos locales (deben ser serializables [java.io.Serializable], si no
excepción): Se crea un nuevo objeto en la MVJ destino, que recibe la
copia
• Por referencia: copia secuenciada del stub del objeto (se envía una instancia
de la clase stub del objeto remoto)
• Objetos remotos: Se crea un nuevo stub en la MVJ destino, que recibe
la copia
• Es necesario tratar mayor número de excepciones que en el caso de invocación
de métodos locales.
Ve
r
si
ón
Pr
e
lim
in
a
r
RMI: Introducción (Cont)
RMI: Localización de objetos remotos (Servicio de nombres)
in
a
r
• JNDI (Java Naming and Directory Interface)
• RMI registry
Pr
e
Cuenta cnt = new CuentaImpl();
String url = “rmi://java.Sun.COM/cuenta”;
// enlazamos una url a un objeto remoto
java.rmi.Naming.bind(url, cnt);
// búsqueda de la cuenta
cnt=(Cuenta)java.rmi.Naming.lookup(url);
lim
Ejemplo:
si
ón
Antes de arrancar el cliente y el servidor, se debe arrancar el programa rmiregistry en el
servidor para el servicio de nombres. El puerto que utiliza el rmiregistry por defecto
es el 1099.
rmiregistry [port_number]
start rmiregistry [port_number]
Ve
r
El método rebind es utilizado normalmente en lugar del método bind, porque garantiza
que si un objeto remoto se registró previamente con dicho nombre, el nuevo objeto
reemplazará al antiguo.
El método rebind almacena en el registro una referencia al objeto con un URL de la
forma:
rmi://<nombre máquina>:<número puerto>/<nombre referencia>
RMI: Búsqueda
r
Cualquier programa que quiera instanciar un objeto remoto debe realizar una búsqueda
de la siguiente forma:
in
a
Sumador misuma = (Sumador)Naming.lookup("rmi://" + args[0] + "/" +"MiSumador");
Pr
e
Servidor:
Enlace a un nombre: bind(), rebind()
lim
El método lookup devuelve una referencia remota a un objeto que implementa la
interfaz remota.
El método lookup interactúa con rmiregistry.
Cliente:
Ve
r
si
ón
Encontrar un objeto y obtener su referencia: lookup()
refObj.nombre_met()
Ve
r
si
ón
Pr
e
lim
in
a
r
RMI: Pasos necesarios
Ve
r
si
ón
Pr
e
in
a
lim
public interface Sumador extends java.rmi.Remote
{
public int sumar(int a, int b)
throws java.rmi.RemoteException;
}
r
RMI: Ejemplo – Programa sumador
RMI: Ejemplo – Programa sumador (Cont)
in
a
r
Clase que implementa la interfase:
lim
import java.rmi.*;
import java.rmi.server.*;
Ve
r
si
ón
Pr
e
public class SumadorImpl extends UnicastRemoteObject implements Sumador {
public SumadorImpl(String name) throws RemoteException {
super();
try {
System.out.println("Rebind Object " + name);
Naming.rebind(name, this);
} catch (Exception e){
System.out.println("Exception: " + e.getMessage());
e.printStackTrace();
}
}
public int sumar (int a, int b) throws RemoteException {
return a + b;
}
RMI: Ejemplo – Programa sumador (Cont)
in
a
r
Servidor:
lim
import java.rmi.*;
import java.rmi.server.*;
Ve
r
si
ón
Pr
e
public class SumadorServer {
public static void main (String args[]) {
String URLRegistro = “rmi://localhost/MiSumador”;
try {
SumadorImpl misuma = new
SumadorImpl(URLRegistro);
} catch(Exception e) {
System.err.println("System exception" + e);
}
}
}
RMI: Ejemplo – Programa sumador (Cont)
in
a
r
Cliente:
lim
import java.rmi.*;
import java.rmi.server.*;
Ve
r
si
ón
Pr
e
public class SumadorClient {
public static void main(String args[]){
int res = 0;
try {
System.out.println("Buscando Objeto ");
Sumador misuma = (Sumador)Naming.lookup("rmi://" + args[0] + "/"
+"MiSumador");
res = misuma.sumar(5, 2);
System.out.println("5 + 2 = " + res);
}
catch (Exception e){
System.err.println(" System exception");
}
System.exit(0);
}
}
RMI: Ejemplo – Como ejecutar
in
a
r
Compilación
javac Sumador.java
javac SumadorImpl.java
javac SumadorClient.java
javac SumadorServer.java
lim
Generación de los proxies
rmic SumadorImpl
Pr
e
Ejecución del programa de registro de RMI
rmiregistry [número puerto]
(Por defecto, en número de puerto es el 1099)
ón
Ejecución del servidor
java SumadorServer
si
Ejecución del cliente
java SumadorCliente <host-del-servidor>
Ubicación de archivos
Ve
r
Nodo cliente:
• Sumador.class
• SumadorClient.class
• SumadorImpl_Stub.class
•
•
•
Nodo servidor:
• Sumador.class
SumadorServer.class
SumadorImpl.class
SumadorImpl_Stub.class
• SumadorImpl_Skel.class
Ve
r
si
ón
Pr
e
lim
ICE
in
a
r
ICE: Internet Comunication Engine
in
a
r
Es un protocolo diseñado por 4 integrantes del Core de CORBA que tiene la misma
filosofía que éste pero con mayores facilidades.
ón
Ve
r
si
Creadores:
• Marc Laukien
• Michi Henning
• Matthew Newhook
• Mark Spruiell
Pr
e
lim
Como principales ventajas contra CORBA podemos encontrar:
• Más fácil de usar y aprender
• Más escalable
• Mayor cantidad de lenguajes soportados
• ICE para RUBY
• Rápida aceptación en el mercado
ICE: Servicios
Ve
r
si
ón
Pr
e
lim
in
a
r
• Slice: El lenguaje de especificación para Ice. Establece el contacto entre servidores y
clientes y además es utilizado para describir datos persistentes.
Compiladores Slice: Las especificaciones en Slice se pueden compilar en varios
lenguajes de programación: C++, Java, Pitón, PHP, C# y Visual Basic. Los servidores
y clientes Ice trabajan juntos, a pesar del lenguaje de programación.
• Ice: El núcleo de librerías Ice, entre otras características este paquete gestiona todas
las tareas de comunicación utilizando un protocolo de altamente eficiente,
proporciona soporte de hilos para servidores multihilo y funcionalidades adicionales
para soportar escalabilidad extrema con a priori millones de objetos Ice.
• IceUtil: una colección utilidades como manejo de Unicote y programación con hilos
(C++ solo).
• IceBox: Un servidor de aplicación especifico para aplicaciones Ice. IceBox puede
ejecutar y administrar servicios Ice que son cargados dinámicamente como una DLL,
librería compartida o clase Java.
• IceGrid: Un sofisticado servidor de activación y herramienta de despliegue para
computación grid avanzada.
• Freeze: proporciona persistencia automática para servants Ice. Con unas pocas
líneas de código, una aplicación puede incorporar un vector altamente escalable que
gestiona eficientemente objetos persistentes.
ICE: Servicios (Cont)
Ve
r
si
ón
Pr
e
lim
in
a
r
• FreezeScript: es necesario para cambiar tipos de datos persistentes, especialmente
en proyectos software grandes. Para minimizar el impacto de estos cambios,
FreezeScript proporciona herramientas de inspección y migración para bases de
datos Freeze. La herramienta soporta scripts basados en XML ya que es potente y
fácil de usar.
• IceSSL: Un plug-in de transporte SSL dinámico para el núcleo Ice. Proporciona
autenticación, encriptación e integridad de mensaje, utilizando un protocolo SSL
estándar.
• Glaciar: Algunos retos de los sistemas middleware son la seguridad y los firewalls.
Glaciar es una solución firewall de Ice, que simplifica el despliegue de aplicaciones
seguras. Autentica y filtra las solicitudes de los clientes y permite callbacks al cliente
de una manera segura. Utilizado en combinación con IceSSL, proporciona una
solución segura que no permite intrusos y es fácil de configurar.
• IceStorm: un servicio de mensajería que soporta la federación. En comparación con
otros servicios de mensajería o eventos, IceStorm soporta tipado de eventos,
entendiendo que la difusión de un mensaje en una federación es tan fácil como
invocar un método sobre un interfase.
• IcePath: es un servicio de parcheado para distribuciones software. Mantener el
software actualizado es una tarea tediosa. IcePath automatiza las actualizaciones
tanto de archivos individuales y de jerarquías de directorios. Solo los archivos
modificados son descargados en las maquinas cliente, utilizando eficientemente
algoritmos de compresión.
ICE: Arquitectura
Pr
e
lim
in
a
r
El cliente y el servidor consisten en una mezcla del código del uso, del código de la
biblioteca, y del código generado de definiciones de la Capa:
Ve
r
si
ón
• Ice Core (núcleo): Mucho de este código se refiere a los detalles de establecimiento de
una red, establecimiento de una red-relacionadas que deseamos guardar lejos de código
del uso. La base del Ice se proporciona como un número de bibliotecas que el cliente y el
servidor se conectan.
• El código del Proxy se genera de tus definiciones de la capa y, por lo tanto, específico a
los tipos de objetos y datos que has definido en la capa.
• El código Skeleton (esqueleto) también se genera de tu definición de la capa y, por lo
tanto, específico a los tipos de objetos y de datos que has definido en la capa. El código
del lado servidor es equivalente del código del Proxy del lado cliente. El esqueleto también
contiene código que ordena y desordena, así que el servidor puede recibir los parámetros
enviados por el cliente, y vuelve parámetros y excepciones al cliente.
• El adaptador del objeto es una parte del ICE API que es específico del lado del servidor:
solamente los servidores utilizan los adaptadores del objeto. Un adaptador del objeto tiene
varias funciones.
ICE: Servidor
in
a
r
#include <Ice/Ice.h>
#include <Printer.h>
using namespace std;
using namespace Demo;
Pr
e
lim
class Printerl : public Printer {
public:
virtual void printString( const string& s, const Ice::Current&);
};
ón
void Printerl:: printString( const string& s, const Ice::Current&) {
cout << s << endl;
}
Ve
r
si
int main(int argc, char* argv[]) {
int status = 0;
Ice::CommunicatorPtr ic;
try {
ic = Ice::initialize(argc, argv);
Ice::ObjectAdapterPtr adapter = ic->createObjectAdapterWithEndpoints (
“SimplePrinterAdapter”, “default –p 10000”);
Ice::ObjectPtr object = new Printerl;
adapter->add(object, ic->stringToldentity(“SimplePrinter”));
ic->waitForShutdown();
}
ICE: Servidor (Cont)
in
a
r
catch (const Ice::Exception& e) {
cerr << e << endl;
status = 1;
}
if (ic) {
try {
ic->destroy();
Ve
r
si
ón
}
catch (const Ice::Exception& e) {
cerr << e << endl;
status = 1;
}
return status;
} //FIN SERVIDOR
Pr
e
lim
catch (const char* msg) {
cerr << msg << endl;
status = 1;
}
ICE: Cliente
Ve
r
si
ón
Pr
e
lim
in
a
r
#include <Ice/Ice.h>
#include <Printer.h>
using namespace std;
using namespace Demo;
int main(int argc, char* argv[]) {
int status = 0;
Ice::CommunicatorPtr ic;
try { ic = Ice::initialize(argc, argv);
Ice::ObjectPrx base = ic->stringToProxy (“SimplePrinter:default –p 10000”);
PrinterPrx printer = PrinterPrx::checkedCast(base);
if(!printer)
throw “Invalid proxy”;
printer->printString(“Hello World!”);
}
catch (const Ice::Exception& ex) {
cerr << ex << endl;
status = 1;
}
catch (const char* msg) {
cerr << msg << endl;
status = 1;
}
if (ic)
ic->destroy();
return status;
} //FIN CLIENTE