June 5th, 2007Programación con C# y .NET Remoting/Mono Remoting [3/7]
Indice general de los manuales
- Introducción, instalación en Ubuntu y creación de una calculadora.
- Modos de compartición de objetos. Creando nuestra primera calculadora distribuida.
- Modos de compartición de objetos: Singlecall. « [Leyendo]
- Modos de compartición de objetos: Singleton.
- Modos de compartición de objetos: CAO.
- Canales: TCP y HTTP. Configuración en archivo XML.
- Uso de interfaces para separar el código entre cliente y servidor.
SingleCall
El código fuente de este tutorial te lo puedes bajar desde aquí.
Como se explicó en el anterior capítulo, SingleCall es una de las posibles formas en la que el servidor comparte una clase. De esta forma, los clientes podrán hacer instancias a los métodos de una clase remota sin guardar el estado. Esto es así ya que una vez que al servidor se le hace la petición de invocar ese método, éste crea una instancia del objeto de esa clase, ejecuta el método, y vuelve a destruir el objeto creado.

Como podemos ver en el ejemplo, los objetos se crean y se destruyen una vez que el cliente ha obtenido una respuesta del método que ha llamado.
Por fin, vamos a pasar a la acción y a crear un cliente y un servidor. El servidor usará la forma de compartir SingleCall, y sacaremos algunas conclusiones de la ejecución:
El código del servidor será:
- // Archivo: Servidor.cs
- // Descripcion: programa servidor que comparte
- // la clase Calculadora remotamente.
- // Biblioteca estandar y remoting
- using System;
- using System.Runtime.Remoting;
- // Bibliotecas para usar un canal HTTP
- using System.Runtime.Remoting.Channels;
- using System.Runtime.Remoting.Channels.Http;
- using Calculo;
- public class Servidor
- {
- // arg[0] representa el puerto del servidor
- public static void Main (string[] args)
- {
- // Creamos un nuevo objeto para el canal HTTP
- HttpChannel chnl = new HttpChannel(int.Parse(args[0]));
- // Le decimos a la máquina que nos reserve ese canal
- ChannelServices.RegisterChannel(chnl);
- // Opciones para la comparticion de la clase
- RemotingConfiguration.RegisterWellKnownServiceType(
- typeof(Calculo.Calculadora),
- “Calculadora.remota”,
- WellKnownObjectMode.SingleCall);
- // Mensajes de espera en la pantalla
- Console.WriteLine(“Atendiendo las peticiones…”);
- Console.WriteLine(“Pulse Enter para salir…”);
- Console.ReadLine();
- }
- }
Como podemos ver, el código del servidor es realmente simple. Creamos un canal por el que vamos a escuchar cuando nos hagan peticiones para usar la clase. La única parte que no hemos comentado en el código es las opciones de la compartición. Para compartir una clase, primero deberemos decir que clase queremos compartir, así pues, recogemos la clase Calculadora que tenemos en el espacio de nombres Calculo “typeof(Calculo.Calculadora)”. Después asignamos un nombre con el que los clientes deben referirse a nuestra clase (como veremos en el código del cliente), que hemos llamado “Calculadora.remota”, pero que puede ser otro cualquiera. Y la parte más importante es la forma en la que compartimos la clase: “SingleCall”. Una vez que el servidor está compartiendo la clase, “pararemos” el programa con la espera de una lectura por teclado.
El código del cliente es igual de simple y parecido:
- // Archivo: Cliente.cs
- // Descripcion: cliente que usara la clase remota Calculadora
- // Biblioteca estandar y remoting
- using System;
- using System.Runtime.Remoting;
- // Bibliotecas para usar un canal HTTP
- using System.Runtime.Remoting.Channels;
- using System.Runtime.Remoting.Channels.Http;
- using Calculo;
- public class Cliente
- {
- // arg[0] representa el host del servidor
- // arg[1] representa el puerto del servidor
- public static void Main (string[] args)
- {
- // Creamos un nuevo objeto para el canal HTTP
- HttpChannel chnl = new HttpChannel();
- // Le decimos a la máquina que nos reserve ese canal
- ChannelServices.RegisterChannel(chnl);
- // Opciones para la utilizacion remota de la clase
- RemotingConfiguration.RegisterWellKnownClientType(
- typeof(Calculo.Calculadora),
- “http://” + args[0] + “:” + args[1] + “/Calculadora.remota”);
- // Ahora, usamos la calculadora como si la clase
- // la tuvieramos en nuestro ordenador
- Calculadora calc = new Calculadora();
- Console.WriteLine(“Suma 2+2 = “ + calc.Suma(2.0, 2.0));
- Console.WriteLine(“Potencia 10^5 = “ + calc.Potencia(5.0));
- // Vamos a comprobar como no se guarda el estado
- calc.LaBase = 5.0;
- Console.WriteLine(“Hemos cambiado la base a 5.0″);
- Console.WriteLine(“Pero la base es: “ + calc.LaBase);
- try
- {
- Console.WriteLine(“Division 8/2 = “ + calc.Divide(8.0,2.0));
- Console.WriteLine(“Division 5/0 = “ + calc.Divide(5.0,0.0));
- }
- catch (Exception e)
- {
- Console.WriteLine(e);
- }
- }
- }
El cliente, al igual que el servidor, necesita registrar el canal por el cual va a hacer las peticiones. Después necesitará recoger el tipo de la clase que se comparte remotamente, y también deberá indicar la dirección en la que se proporciona el servicio. Como vemos, al cliente no hay que especificarle que el servidor está compartiendo su clase de forma SingleCall.
Ahora compilaremos los tres archivos para hacer las pruebas:
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
Ejecutaremos en una consola el servidor:
./Servidor.exe 9999
Y en otra consola el cliente:
./Cliente.exe localhost 9999
Observamos el resultado del servidor:
Atendiendo las peticiones…
Pulse Enter para salir…
Constructor.
Metodo: Suma.
Constructor.
Metodo: Potencia.
Constructor.
Constructor.
Constructor.
Metodo: Divide.
Constructor.
Metodo: Divide.
Al meter una traza en el constructor de la calculadora, podemos observar que cada vez que hacemos una llamada a un método, se llama al constructor, es decir, el servidor crea una nueva instancia de la calculadora.
Y ahora la salida del cliente:
Suma 2+2 = 4
Potencia 10^5 = 100000
Hemos cambiado la base a 5.0
Pero la base es: 10
Division 8/2 = 4
System.Exception: Division por 0
…
Podemos ver dos cosas interesantes:
- Como recordaremos, el atributo laBase se inicializa a 10 cada vez que se llama al constructor de la calculadora. Aunque en una instrucción hayamos cambiado LaBase a 5.0, al volverla a recoger en una instrucción posterior, será 10. Podemos observar que el objeto no ha guardado el estado, o mejor dicho, en realidad eran dos instancias de la clase calculadora.
- La segunda cosa interesante que podemos ver es que las excepciones las recoge el cliente, así el servidor será seguro y no se interrumpirá.
Todavía nos quedan muchas cosas por ver: elegir un canal TCP en lugar de HTTP, controlar la vida de los objetos, como compilar el cliente sin la clase implementada Calculadora, etc. Aunque lo dejamos aquí para que podáis ir probando y contándome vuestras dudas.
Indice general de los manuales
- Introducción, instalación en Ubuntu y creación de una calculadora.
- Modos de compartición de objetos. Creando nuestra primera calculadora distribuida.
- Modos de compartición de objetos: Singlecall. « [Leyendo]
- Modos de compartición de objetos: Singleton.
- Modos de compartición de objetos: CAO.
- Canales: TCP y HTTP. Configuración en archivo XML.
- Uso de interfaces para separar el código entre cliente y servidor.



