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