Hola Mundo con ZeroC Ice#

En este capítulo vamos a ver, tras lo aprendido en el capítulo anterior, como integrar la clase anterior en un servidor Ice y como implementar un cliente para la misma.

Interfaz#

Como comentamos, es imprescindible definir una interfaz de comunicación para que los clientes sepan qué métodos pueden invocar y qué argumentos son necesarios y cuáles esperar como valor de retorno.

module Example {
  interface Printer {
    void write(string message);
  };
};

Descarga

Servidor de Hola Mundo#

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import sys
import Ice
Ice.loadSlice("Printer.ice")
import Example


class ConsolePrinter(Example.Printer):
    def write(self, message, current=None):
        print(message, flush=True)


class Server(Ice.Application):
    def run(self, argv):
        broker = self.communicator()
        servant = ConsolePrinter()

        adapter = broker.createObjectAdapter("PrinterAdapter")
        proxy = adapter.add(servant, broker.stringToIdentity("printer1"))

        print(proxy, flush=True)

        adapter.activate()
        self.shutdownOnInterrupt()
        broker.waitForShutdown()

        return 0


if __name__ == "__main__":
    server = Server()
    sys.exit(server.main(sys.argv))

Descarga

Además del sirviente, ya visto y explicado en profundidad en el apartado anterior, haremos uso de Ice.Application.

Esta clase es una utilidad que ofrece ZeroC ICE a los desarrolladores de aplicaciones para poder crear servidores de manera mucho más sencilla.

Desde el punto de vista del desarrollador, lo único que hay que hacer es lo siguiente:

  1. Crear una clase que herede de Ice.Application.

  2. Implementar el método run, que acepta un argumento. El código dentro del método será el que se ejecute cuando la aplicación se ejecute en el siguiente paso.

  3. Crear un objeto de nuestra nueva clase y llamar a su método main, pasándole la línea de argumentos (o una variable equivalente).

Internamente, el método main, que es heredado de la Ice.Application, realizará una serie de inicializaciones de ICE y finalmente llamará al método run que hemos definido.

En nuestro ejemplo, el código realiza las 4 operaciones que cualquier servidor ICE realizara:

  1. Inicializar y activar el adaptador de objetos.

  2. Crear el sirviente (o sirvientes) y añadirlos al adaptador de objetos.

  3. Configurar el modo de salida (shutdownInInterrupt). En este caso se realizará un shutdown del broker de comunicación cuando se reciba una interrupción.

  4. Activar el modo de espera del broker: waitForShutdown.

Cliente de Hola Mundo#

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import sys
import Ice
Ice.loadSlice('Printer.ice')
import Example


class Client(Ice.Application):
    def run(self, argv):
        proxy = self.communicator().stringToProxy(argv[1])
        printer = Example.PrinterPrx.checkedCast(proxy)

        if not printer:
            raise RuntimeError('Invalid proxy')

        printer.write('Hello World!')

        return 0


sys.exit(Client().main(sys.argv))

Descarga

Para el cliente hemos vuelto a utilizar la misma Ice.Application, aunque en esta ocasión los pasos que realiza el método run son algo diferentes, al tratarse de un cliente puro:

  1. Generamos un proxy genérico a partir del stringfied proxy que recibimos por la línea de argumentos.

  2. Tratamos de hacer una conversión desde ese proxy genérico a un Example.PrinterPrx, utilizando el método checkedCast.

  3. Si la conversaión falla, el método anterior devolverá un None, y saldremos.

  4. Si la conversión fue bien, usaremos el proxy para realizar una invocación remota al método write.