Sei sulla pagina 1di 14

Introduccin

.Net Remoting es un entorno (framework) para la construccin de sistemas distribuidos. Como cualquier framework de esta naturaleza, .Net Remoting nos aporta una serie de servicios (incluyendo la creacin y gestin del tiempo de vida de los objetos) y mecanismos para el transporte de los mensajes entre objetos que se denominan canales. Nuestro objetivo a la hora de crear estas prcticas es ver como usar estos servicios y mecanismos mediante una sucesin de ejemplos, quizs algo sencillos al principio pero que ganarn en riqueza a lo largo del curso. El entorno de desarrollo que os recomendamos es Mono y algunas herramientas adicionales como Nant o Nunit, pero podis usar el entorno que ms os guste siempre y cuando los ejecutables finales de las prcticas funcionen correctamente en los laboratorios. Si alguno prefiere utilizar un entorno integrado para el desarrollo os propongo SharpDevelop o MonoDevelop. En los web respectivos podris encontrar las instrucciones para la descarga e instalacin de todas estas herramientas.

Curso de Remoting. Prctica 1.

1 de 14

Primer ejemplo
Al principio vamos a construir una pequea aplicacin que nos permitir familiarizarnos con C# y con el entorno de desarrollo. Vamos a utilizar un ejemplo muy usual en este tipo de cursos: una calculadora. Esta aplicacin ser inicialmente local (no remota) y posteriormente la vamos a transformar en una aplicacin distribuida. El primer paso pues ser definir la clase de la calculadora. Os proponemos un cdigo de ejemplo, pero os aconsejamos que intentis crear uno vosotros mismos.

// Calculadora.cs using System; namespace Calculo { public class Calculadora { public double Suma(double izq, double dch) { return izq+dch; } public double Producto(double izq, double dch) { return izq*dch; } } }

Para usar este cdigo vamos a construir un programa principal que har llamadas a dicha clase. Un ejemplo sera:

Curso de Remoting. Prctica 1.

2 de 14

// Principal.cs using System; using Calculo; public class Principal { public static void Main (string[] args) { Console.WriteLine("Esto es una prueba"); Calculadora calc = new Calculadora(); Console.WriteLine("Suma 5+3=" + calc.Suma(5,3)); Console.WriteLine("Producto (5,3)); } } 5*3=" + calc.Producto

Para compilar este cdigo con Mono tendris que teclear:


mcs -target:library Calculadora.cs mcs -r:Calculadora.dll Principal.cs

Si, en lugar de utilizar los comandos de Mono, os gusta ms usar herramientas de construccin automtica, os recomiendo NAnt. Dicha herramienta es la versin para . Net de otra herramienta llamada Ant, muy utilizada en el entorno Java. Otra herramienta que podis usar para el mismo propsito sera make. Si optis por NAnt, os propongo un fichero de configuracin de ejemplo:

Curso de Remoting. Prctica 1.

3 de 14

<?xml version="1.0"?> <project name="Calculadora" default="build" basedir="."> <description>Un ejemplo para las practicas.</description> <property name="debug" value="true" overwrite="false" /> <property name="build.dir" value="." /> <property name="Calculo.dll" value="Calculo.dll" /> <property name="Servidor.exe" value="Servidor.exe" /> <target name="clean" description="Borra los ficheros generados"> <delete> <fileset> <include name="${build.dir}/*.dll"/> <include name="${build.dir}/*.pdb"/> <include name="${build.dir}/*.exe"/> </fileset> </delete> </target> <target name="calculo" depends="clean" description="Compila la calculadora"> <csc target="library" output="${build.dir}/${Calculo. dll}" debug="${debug}"> <sources> <include name="Calculadora.cs" /> </sources> </csc> </target> <target name="build" depends="calculo" description="Compila los fuentes"> <csc target="exe" output="${build.dir}/${Servidor.exe}" debug="${debug}"> <sources> <include name="Servidor.cs" /> </sources> <references> <include name="${build.dir}/${Calculo.dll}"/> </references> </csc> </target> </project>

En nuestro primer ejemplo nos haran falta otras operaciones tales como dividir o Curso de Remoting. Prctica 1. 4 de 14

restar. Lo dejamos para que lo hagis vosotros mismos como ejercicio. Otra mejora que necesitaremos en breve es la definicin de un interface para la calculadora. Os recomiendo que sigis la nomenclatura habitual en C# y la denominis ICalculadora. Haced que vuestra calculadora herede (extienda) vuestro interface. Finalmente os recomiendo que insertis alguna traza en las funciones de la clase calculadora; de esta forma podremos observar donde se est ejecutando el objeto cuando pasemos al modelo distribuido.

Curso de Remoting. Prctica 1.

5 de 14

Segundo ejemplo
Ahora vamos a transformar la aplicacin anterior para que tenga un funcionamiento distribuido. Antes de seguir, nuestra calculadora necesita una pequea modificacin. Tenemos que indicar al sistema que nuestra clase pasa a ser un objeto remoto. Para ellos hacemos heredar la clase de otra clase llamada System.MarshalByRefObject. Por ejemplo:

// Calculadora.cs using System; namespace Calculo { public class Calculadora : System.MarshalByRefObject { ... el resto del cdigo ... } }

Con esto le estamos indicando al sistema que la clase puede ser referenciada. Es decir, que podemos crear una referencia o puntero al objeto, aunque en lugar de almacenar una direccin de memoria, se utilizar informacin ms compleja (mquina, servicio, etc.). Es la forma que tiene el cliente de acceder a la informacin del objeto almacenada en el servidor. Tambin necesitaremos un servidor que atienda las peticiones de los clientes y que sea el que realmente cree el objeto de tipo Calculadora. Los clientes harn llamadas a la calculadora, pero esas llamadas sern ejecutadas en el proceso servidor (que incluso podr estar otra mquina diferente). El cdigo del servidor ser realmente simple:

Curso de Remoting. Prctica 1.

6 de 14

// Servidor.cs using System; using System.Runtime.Remoting; using Calculo; public class Servidor { public static void Main (string[] args) { RemotingConfiguration.Configure("Servidor.config"); Console.WriteLine("Atendiendo las peticiones..."); Console.WriteLine("Pulse Enter para salir..."); Console.ReadLine(); } }

Ms sencillo imposible, no?. Realmente la nica instruccin que no conocemos es la llamada a RemotingConfiguration.Configure. En dicha instruccin le indicamos que la configuracin del servidor se especifica en un fichero denominado Servidor.config. El contenido de dicho fichero sera algo del estilo:

<configuration> <system.runtime.remoting> <application> <service> <wellknown mode="SingleCall" type="Calculo.Calculadora, Calculo" objectUri="Calculadora.remota" /> </service> <channels> <channel ref="http" port="1234"/> </channels> </application> </system.runtime.remoting> </configuration>

Como podemos observar el fichero de configuracin tiene una estructura tpica de XML. El primer nivel le indica que es un fichero de configuracin y el segundo (el elemento <system.runtime.remoting>) que la configuracin se refiere al sistema de Curso de Remoting. Prctica 1. 7 de 14

remoting. Vemos tambin que hay un punto donde indicamos el tipo de protocolo a utilizar (http) y el puerto (1234) en el que escuchar el servidor. Por ahora no vamos a entrar en ms detalle y pasemos a construir un cliente que utilice nuestra calculadora. Tambin ser bastante simple. Os propongo el siguiente ejemplo:

// Servidor.cs using System; using System.Runtime.Remoting; using Calculo; public class Cliente { public static void Main (string[] args) { Console.WriteLine("Esto calculadora"); RemotingConfiguration.Configure("Cliente.config"); Console.WriteLine("Creando la calculadora"); Calculadora calc = new Calculadora(); Console.WriteLine("Prueba de suma 5+3=" + calc.Suma (5,3)); Console.WriteLine("Prueba calc.Producto(5,3)); } } de producto 5*3=" + es una prueba de

Uff. No parece muy difcil, verdad? Hemos cambiado muy poco nuestra aplicacin. nicamente hemos introducido la misma instruccin que en el servidor. Es decir, hemos hecho una llamada a RemotingConfiguration.Configure. Para el cliente hemos preparado otro fichero de configuracin muy similar al anterior:

Curso de Remoting. Prctica 1.

8 de 14

<configuration> <system.runtime.remoting> <application> <client> <wellknown type="Calculadora, Calculo" url="http://localhost:1234/Calculadora.remota" /> </client> </application> </system.runtime.remoting> </configuration>

Al igual que el fichero de configuracin del servidor, tenemos un fichero XML con un elemento de configuracin y otro propio de remoting. La diferencia est en el nivel de aplicacin. En el servidor se configura los servicios (elemento <service>) a los que debe atender y los canales a utilizar (elemento <channels>). El cliente nicamente especifica que la clase calculadora est siendo servida en la URL indicada (http://localhost:1234/Calculadora.remota). Si tienes alguna duda sobre como interpretar una url, te aconsejamos que preguntes a tu profesor. En nuestro caso, la url est indicando un protocolo Http, a una mquina local (localhost) y utilizando el puerto 1234, dentro de esta mquina queremos utilizar el recurso denominado Calculadora.remota. Probad a compilar y ejecutar el ejemplo. Os propongo un nuevo fichero nant que podris adaptar a vuestras necesidades:

Curso de Remoting. Prctica 1.

9 de 14

<?xml version="1.0"?> <project name="Calculadora" default="build" basedir="."> <description>Un ejemplo para las practicas.</description> <property name="debug" value="true" overwrite="false" /> <property name="build.dir" value="." /> <property name="calculo.dll" value="Calculo.dll" /> <property name="servidor.exe" value="Servidor.exe" /> <property name="cliente.exe" value="Cliente.exe" /> <target generados"> <delete> <fileset> <include name="${build.dir}/*.dll"/> <include name="${build.dir}/*.pdb"/> <include name="${build.dir}/*.exe"/> </fileset> </delete> </target> <target name="calculo" depends="clean" description="Compila la calculadora"> <csc target="library" output="${build.dir}\${calculo.dll} " debug="${debug}"> <sources> <include name="Calculadora.cs" /> </sources> </csc> </target> <target name="Servidor" depends="calculo" name="clean" description="Borra los ficheros

description="Compila el servidor"> <csc target="exe" output="${build.dir}\${servidor.exe}" debug="${debug}"> <sources> <include name="Servidor.cs" /> </sources> <references> <include name="${build.dir}/${calculo.dll}"/> </references> </csc> </target> <target name="Cliente" depends="calculo" description="Compila el cliente"> <csc target="exe" output="${build.dir}/${cliente.exe}" debug="${debug}">

Curso de Remoting. Prctica 1.

10 de 14

<sources> <include name="Cliente.cs" /> </sources> <references> <include name="${build.dir}/${calculo.dll}"/> </references> </csc> </target> <target </target> </project> name="build" depends="Servidor, Cliente" description="Compila el cliente y el servidor">

Si todo ha ido correctamente, el objeto calculadora ya no se ejecuta en el cliente. Podis comprobarlo si habis puesto alguna traza en las funciones sumar o multiplicar de la clase calculadora segn os recomendamos en el primer paso. Ahora debemos observar que las trazas aparecen en la consola donde est corriendo el servidor. Si no es as o tienes dudas, pregunta a tu profesor antes de continuar. Relacionado con este ejemplo, ahora os proponemos varios ejercicios: 1.- Completa la calculadora con otras funciones que utilicen todos los tipos bsicos: strings, byte, char, short, int, long double, etc. Tanto con signo como sin l. Haz varias pruebas. Podrs comprobar que el sistema es transparente. nicamente tendrs que cambiar la clase calculadora y el programa cliente que lo realiza las pruebas. 2.- Introduce una funcin de dividir que detecte si el divisor es cero, en cuyo caso levanta una exception estndar pero con un mensaje propio. Algo del estilo:
if (divisor == 0) throw new Exception("Dividiendo por cero");

Pon en el cliente llamadas para probar la divisin normal y con excepciones. Atrapar la excepcin e imprime el mensaje de la misma. Haz primero la prueba en la aplicacin local y vuelve a probarlo en la aplicacin remota. Si has realizado todo correctamente, podrs observar que las excepciones tambin se transmiten remotamente y que son transparentes al programador. 3.- Nuestra calculadora utiliza double pero en las llamadas de prueba hemos utilizado enteros. Observa el comportamiento de la conversin entre tipos (casting). Para ello define otras funciones que utilicen enteros o llama a las funciones con una combinacin de enteros y doubles. Por ejemplo:
Console.WriteLine("Division 11/2=" + calc.Divide(11,2)); Console.WriteLine("Division 11/2=" + calc.Divide(11.0,2)); Console.WriteLine("Division 11/2=" + calc.Divide(11,2.0)); Console.WriteLine("Division 11/2=" + calc.Divide(11.0,2.0));

Observa como la conversin de tipos es tambin transparente al programador. De hecho, con nuestros conocimientos actuales an no podramos decir si la conversin Curso de Remoting. Prctica 1. 11 de 14

se hace en el cliente o el servidor. 4.- Prueba a cambiar el nombre del recurso o servicio (Calculadora.remota) y el nmero del puerto (1234). Tendrs que cambiar tanto la configuracin de servidor como del cliente. Prueba a ejecutar el servidor en una mquina y el cliente en otra. 5.- Tambin podemos cambiar el protocolo de http a tcp del servidor. Para probarlo modifica la configuracin y cambia http por tcp. Tendrs que cambiar tanto la configuracin de servidor como del cliente. Cuando ests seguro que te funciona haz que el servidor atienda a dos canales diferentes a la vez (uno en tcp y otro en http). Para ello crea dos entradas <channels> en el fichero de configuracin del servidor. No uses el mismo nmero de puerto para los dos canales. Ahora prueba a ejecutar dos clientes, uno que solicite servicios de calculadora usando http y otro que use tcp (lo ms rpido es que crees otro directorio para la aplicacin cliente) sin parar el servidor. 6.- Define una funcin en la clase calculadora que calcule la potencia de una base con la siguiente forma:

private double base = 10.0; public double Base { get {...} set {...} } public double Potencia(double valor) { ... }

La funcin deber retornar el valor de la base elevado al nmero que toma por parmetro. Adems, observa que hemos definido un property (get/set) para trabajar con la base. Prueba a cambiar la base desde tu cliente y despus llama a la funcin Potencia. has obtenido el resultado que esperabas? Seguramente no estas obteniendo el valor esperado. Para descubrir las razones pasa al siguiente ejercicio. 7.- Define un constructor para la calculadora (no te olvides que debe ser pblico) y pon una traza indicando que has pasado por all. Vuelve a ejecutar el cliente y si todo es correcto, podrs observar que se llama al constructor cada vez que haces una llamada a las funciones. Para estar seguro, define una variable esttica que se incremente en el constructor. Imprime en la traza del constructor el valor de dicha variable. Pregunta si tienes dudas de como funciona una variable esttica (tambin se denomina variable de clase). Ejecuta varios clientes y varias veces con un mismo servidor (sin pararlo). Intenta explicar el funcionamiento antes de pasar al siguiente ejercicio. La razn de que cada llamada cree un objeto remoto se debe a que hemos dicho en nuestro fichero de configuracin que el servicio era SingleCall. Este parmetro le indica al sistema que el objeto debe ser creado en cada llamada al mismo. El sistema Curso de Remoting. Prctica 1. 12 de 14

destruye el objeto al terminar la llamada. Suele ser til cuando no interesa mantener informacin entre llamadas. La alternativa sera Singleton que indica que todas las llamadas se refieren al mismo objeto. La vida del objeto (cuando se crea o hasta cuando existe) se define combinando varias caractersticas y sta es una de ellas. Probad a cambiar el modo de activacin y comprobad que las trazas se adaptan a ese nuevo modo. An nos quedan muchas cosas por descubrir sobre la vida del objeto remoto. Por ejemplo, hasta ahora el servidor crea el objeto en el momento en el que se le llama, pero puede interesarnos crearlo al principio. Tampoco sabemos como controlar el instante de la destruccin en el caso Singleton. La forma por defecto hace que pasado un tiempo, el sistema destruye el objeto. Prueba a hacer varias llamadas a un servidor en modo Singleton, haciendo pasar varios minutos entre llamada. Observad como pasado cierto tiempo (unos 5 minutos) el objeto se vuelve a crear y eso es seal de que se ha destruido el anterior.

Curso de Remoting. Prctica 1.

13 de 14

Resumen
A lo largo de esta prctica hemos aprendido a construir nuestra primera aplicacin distribuida con Remoting. Hemos visto como Remoting nos permite construir una aplicacin distribuida de forma muy sencilla y casi transparente al programador. Hemos visto como Remoting trabaja con los tipos bsicos y excepciones. Tambin hemos aprendido que las aplicaciones remoting pueden ser configuradas mediante ficheros XML; creando varias configuraciones en las que hemos combinado los canales y protocolos bsicos. Finalmente hemos trabajado con una de las primeras caractersticas que definen el tiempo de vida de un objeto.

Curso de Remoting. Prctica 1.

14 de 14

Potrebbero piacerti anche