Indice general de los manuales

  1. Introducción, instalación en Ubuntu y creación de una calculadora.
  2. Modos de compartición de objetos. Creando nuestra primera calculadora distribuida.
    1. Modos de compartición de objetos: Singlecall.
    2. Modos de compartición de objetos: Singleton.  «  [Leyendo]
    3. Modos de compartición de objetos: CAO.
  3. Canales: TCP y HTTP. Configuración en archivo XML.
  4. Uso de interfaces para separar el código entre cliente y servidor.

Singleton

Ésta es otra de las formas que vimos en las que el servidor puede compartir un objeto. De esta forma el servidor creará un objeto único para todos los clientes y podrá guardar el estado. Así, los clientes podrán compartir información de ese objeto entre ellos.

singleton

Como podemos ver, los clientes comparten la misma calculadora. El cliente1 cambia uno de los atributos del objeto (cambia el estado) y el cliente2 se percata de ello.

El código del servidor es igual que el del tutorial anterior, aunque solo habrá que decirle que comparta la calculadora en modo Singleton. Modificaremos la siguiente línea:

  1. // Archivo: Servidor.cs
  2. // Descripcion: programa servidor que comparte
  3. // la clase Calculadora remotamente.
  4.  
  5. // Biblioteca estandar y remoting
  6. using System;
  7. using System.Runtime.Remoting;
  8.  
  9. // Bibliotecas para usar un canal HTTP
  10. using System.Runtime.Remoting.Channels;
  11. using System.Runtime.Remoting.Channels.Http;
  12. using Calculo;
  13.  
  14. public class Servidor
  15. {
  16.   // arg[0] representa el puerto del servidor
  17.   public static void Main (string[] args)
  18.   {
  19.     // Creamos un nuevo objeto para el canal HTTP
  20.     HttpChannel chnl = new HttpChannel(int.Parse(args[0]));
  21.  
  22.     // Le decimos a la máquina que nos reserve ese canal
  23.     ChannelServices.RegisterChannel(chnl);
  24.  
  25.     // Opciones para la comparticion de la clase
  26.     RemotingConfiguration.RegisterWellKnownServiceType(
  27.       typeof(Calculo.Calculadora),
  28.       “Calculadora.remota”,
  29.       WellKnownObjectMode.Singleton);
  30.  
  31.     // Mensajes de espera en la pantalla
  32.     Console.WriteLine(“Atendiendo las peticiones…”);
  33.     Console.WriteLine(“Pulse Enter para salir…”);
  34.     Console.ReadLine();
  35.   }
  36. }

Y el cliente lo dejaremos igual, ya que en el cliente no especificábamos como era la forma en la que compartía el servidor. Aunque vamos a crear otro nuevo servidor para ver como se comparte el objeto entre los dos. Solo escribiré la parte en que se hace uso de la calculadora, el resto del código (crear canal HTTP, reservar el canal, forma en la que se comparte) será igual:

  1. // Archivo: Cliente2.cs
  2. // Descripcion: cliente que usara la clase remota Calculadora
  3.  
  4. // Biblioteca estandar y remoting
  5. using System;
  6. using System.Runtime.Remoting;
  7.  
  8. // Bibliotecas para usar un canal HTTP
  9. using System.Runtime.Remoting.Channels;
  10. using System.Runtime.Remoting.Channels.Http;
  11. using Calculo;
  12.  
  13. public class Cliente2
  14. {
  15.   // arg[0] representa el host del servidor
  16.   // arg[1] representa el puerto del servidor
  17.   public static void Main (string[] args)
  18.   {
  19.     // Creamos un nuevo objeto para el canal HTTP
  20.     HttpChannel chnl = new HttpChannel();
  21.  
  22.     // Le decimos a la máquina que nos reserve ese canal
  23.     ChannelServices.RegisterChannel(chnl);
  24.  
  25.     // Opciones para la utilizacion remota de la clase
  26.     RemotingConfiguration.RegisterWellKnownClientType(
  27.       typeof(Calculo.Calculadora),
  28.       “http://” + args[0] + “:” + args[1] + “/Calculadora.remota”);
  29.  
  30.     // Ahora, usamos la calculadora como si la clase
  31.     // la tuvieramos en nuestro ordenador
  32.     Calculadora calc = new Calculadora();
  33.     Console.WriteLine(“LaBase la hemos cambiado desde el primer cliente…”);
  34.     Console.WriteLine(“Asi que vemos que la base desde el segundo es: “ + calc.LaBase);
  35.    }
  36. }

El código del primer cliente lo podemos conseguir desde el tutorial anterior: Programación con C# y .NET Remoting/Mono Remoting [3/7]

Ahora solo nos queda compilar los archivos:

mcs -target:library Calculo.cs
mcs -r:Calculo.dll -r:System.Runtime.Remoting.dll Servidor.cs
mcs -r:Calculo.dll -r:System.Runtime.Remoting.dll Cliente.cs
mcs -r:Calculo.dll -r:System.Runtime.Remoting.dll Cliente2.cs

Ejecutaremos los archivos en diferentes consolas y con el siguiente orden.

Ejecutar el servidor:

./Servidor.exe 9999

El cliente 1:

./Cliente.exe localhost 9999

Y el cliente 2:

./Cliente2.exe localhost 9999

Observamos el resultado del servidor:

Atendiendo las peticiones…
Pulse Enter para salir…
Constructor.
Metodo: Suma.
Metodo: Potencia.
Metodo: Divide.
Metodo: Divide.

Como podemos ver, solo se llama una vez al constructor, es decir, solo se crea un objeto el cual usarán todos los clientes.

La salida del cliente1:

Suma 2+2 = 4
Potencia 10^5 = 100000
Hemos cambiado la base a 5.0
Pero la base es: 5
Division 8/2 = 4
System.Exception: Division por 0

A diferencia que en SingleCall, una vez que hemos modificado el atributo laBase, este se puede consultar y obtener el último cambio, es decir, se guarda el estado.

Y la salida del cliente2:

LaBase la hemos cambiado desde el primer cliente
Asi que vemos que la base desde el segundo es: 5

Ya que desde el primer cliente cambiamos el atributo laBase, al hacer una consulta desde el segundo, vemos que recogemos el último estado de la calculadora aunque se haya cambiado desde otro cliente.

Vida del objeto

¿Que pasa si dejamos el servidor ejecutándose y pasan 5 minutos (aproximadamente) desde la última llamada de un cliente? Pues que el servidor destruye el objeto. .NET Remoting usa el concepto de vida del objeto para poder destruirlo pasados unos minutos. Prueba a ejecutar el servidor, luego el cliente 1, esperar 5 minutos y ejecutar el cliente 2:

./Servidor.exe 9999

./Cliente.exe localhost 9999

[5 minutos después...]

./Cliente2.exe localhost 9999
LaBase la hemos cambiado desde el primer cliente
Asi que vemos que la base desde el segundo es: 10

El seguimiento de este programa sería:

  1. El servidor crea un nuevo objeto calculadora con el atributo laBase = 10.
  2. El Cliente 1 cambia laBase = 5.
  3. Pasan más o menos cinco minutos, así que el servidor destruye la calculadora.
  4. El Cliente 2 necesita la calculadora, así que el servidor crea un nuevo objeto calculadora con el atributo laBase = 10.
  5. El Cliente 2 usa la calculadora, pero no obtiene el estado que había estado usando el Cliente 1.

Como podemos ver, al pasar un tiempo, el servidor destruye el objeto y el Cliente 2 debe usar un nuevo objeto Calculadora.

Esta forma de destruir los objetos si ningún cliente los utiliza durante un tiempo puede que nos sea de ayuda por temas de la seguridad o de liberación de memoria. Pero si no queremos que el objeto se autodestruya pasado un tiempo, habrá que añadir el siguiente método al código de la clase Calculadora:

  1. public override object InitializeLifetimeService()
  2. {
  3.   // Un truco para que el objeto viva para
  4.   // siempre.
  5.   return null;
  6. }

Sobre la vida de los objetos pasaremos a hablar en otro capítulo, aunque necesitaba remarcarlo por si alguien lo necesita.

Puede que haya ido un poco rápido, esto es así ya que si comprendisteis bien la forma SingleCall, esta forma no os supondría mucha más dificultad. En caso contrario, comentarme vuestras dudas.

Indice general de los manuales

  1. Introducción, instalación en Ubuntu y creación de una calculadora.
  2. Modos de compartición de objetos. Creando nuestra primera calculadora distribuida.
    1. Modos de compartición de objetos: Singlecall.
    2. Modos de compartición de objetos: Singleton.  «  [Leyendo]
    3. Modos de compartición de objetos: CAO.
  3. Canales: TCP y HTTP. Configuración en archivo XML.
  4. Uso de interfaces para separar el código entre cliente y servidor.