REPORTE DE PROYECTO TERMINAL FECHA: 2006 …148.206.53.84/tesiuami/UAMI13918.pdf · •...

74
REPORTE DE PROYECTO TERMINAL FECHA: 2006-05-12 ALUMNO: PEREZ BARILLA JAVIER MATRICULA: 96218809 ASESORA: DRA. GRACIELA ROMAN ALONSO LICENCIATURA: COMPUTACIÓN Reporte de proyecto terminal 1

Transcript of REPORTE DE PROYECTO TERMINAL FECHA: 2006 …148.206.53.84/tesiuami/UAMI13918.pdf · •...

REPORTE DE PROYECTO TERMINAL

FECHA: 2006-05-12 ALUMNO: PEREZ BARILLA JAVIER MATRICULA: 96218809 ASESORA: DRA. GRACIELA ROMAN ALONSO LICENCIATURA: COMPUTACIÓN

Reporte de proyecto terminal 1

Reporte de proyecto terminal

Estudio de C# como herramienta de cómputo distribuido

División: CBI

Asesora: Dra. Graciela Román Alonso

Lugar de Desarrollo: UAM-I

Universidad Autónoma MetropolitanaUAM-I

Carrera: Computación

Matricula: 96218809

Alumno: Javier Pérez Barilla

Periodo de Desarrollo: Del 16-02-2004 al 08-12-2005

Reporte de proyecto terminal 2

..

INDICE

Página 1. Introducción. 3 2. Objetivos. 5 2.1. Objetivos generales. 5 2.2. Objetivos específicos. 5 3. Cómputo Paralelo. 6 3.1. Arquitecturas paralelas. 6 3.2. Algoritmos para la distribución de cómputo. 13 3.3. Recopilación de trabajos similares. 14 4. Introducción al lenguaje de programación C#. 20 4.1. Estudio de la plataforma .NET. 20 4.1.1. Introducción a la plataforma .NET. 20 4.1.2. Instalación del lenguaje de programación C#. 21 4.1.3. Creación de un programa en C#. 22 4.1.4. Compilación y ejecución de un programa creado en C#. 23 4.1.5. Inclusión de librerías para que un programa pueda ser compilado. exitosamente. 25 4.1.6. Análisis de C# para ejecutar procesos en paralelo. 25 4.2. Inicialización del ambiente de trabajo. 26 5. Propuesta de diseño de una aplicación paralela con C#. 27 5.1. Identificación de módulos del sistema. 27 5.2. Propuesta de la arquitectura del sistema. 28 5.3. Funcionalidad de los módulos. 28 5.4. Definición de casos de uso. 31 5.5. Estructuración de cada módulo. 35 6. Objetivos y metas alcanzados. 39 7. Resultados. 40 8. Conclusiones. 55 9. Recomendaciones. 56 10. Bibliografía. 57 ANEXO A 58

Reporte de proyecto terminal 3

1. INTRODUCCION

Los sistemas de cómputo paralelo o distribuido se remontan a los inicios de la computación ya que desde el modelo de BOON NEWMAN encontramos este tipo de arquitecturas. Los sistemas computacionales paralelos o distribuidos surgen debido a la necesidad de crear arquitecturas que ofrezcan una mayor capacidad de recursos de Hardware o bien tratar de aprovechar al máximo los recursos de un conjunto de computadoras conectadas paralelamente (cluster). Al inicio de la computación los recursos de cómputo que demandaba un proceso eran relativamente pequeños por lo que una sola computadora podía cubrir los recursos de Hardware que demandaba un proceso. Pero a medida que se fue avanzando en la computación los procesos demandaban cada vez mas recursos de Hardware hasta llegar al punto en que los recursos de Hardware que demanda un proceso no pueden ser cubiertos por una sola computadora, debido a esto es como surge la necesidad de crear arquitecturas paralelas en los que los recursos de todas las máquinas son compartidas y de esta forma se trata de solucionar el problema de recursos insuficientes de Hardware. Uno de los puntos importantes de nuestro trabajo de investigación fue el determinar si a través de la herramienta C# podía ser posible implementar una aplicación en paralelo. Nuestro trabajo de investigación esta compuesta por dos etapas:

1) Comprende la parte del proyecto de investigación I. En esta etapa se recopilo toda la información teórica sobre el tema de la computación en paralelo, así como de la herramienta que empleamos para el desarrollo del Software de nuestro sistema balanceador de carga empleando la herramienta C#.

2) Comprende la parte del proyecto de investigación II. En esta etapa se empleo toda la información obtenida en la primera etapa de nuestro trabajo de investigación para poder plantear una solución al problema de carga desproporcional en un conjunto de computadoras conectadas en paralelo.

Para la parte del desarrollo del sistema se empleo el lenguaje de programación C# (C Sharp) de la plataforma .NET. El tipo de asignación de trabajo a cada uno de los nodos es de tipo dinámico.

Reporte de proyecto terminal 4

Los motivos por los cuales decidimos emplear en nuestra propuesta el lenguaje de programación C# son:

1. C# es actualmente uno de los lenguajes de programación más populares para aplicaciones en Internet, pero además esta herramienta nos permite desarrollar programas de propósito general entre los cuales se encuentran los programas para ejecutar procesos en paralelo.

2. C# es un lenguaje de programación orientada a objetos, lo que permite desarrollar una amplia gama de aplicaciones explotando al máximo las propiedades de la plataforma .NET.

3. C# ofrece una alternativa a los programadores tradicionales de C y C++ para abordar el desarrollo de aplicaciones complejas con facilidad y rapidez pero sin sacrificar la potencia y el control que ofrecen C y C++.

Reporte de proyecto terminal 5

2. OBJETIVOS

2.1 Objetivos generales. Crear un sistema de computo empleando la tecnología C#. El sistema deberá tener la capacidad de distribuir la carga de trabajo de aplicaciones distribuidas sobre un conjunto de computadoras conectadas en paralelo. 2.2 Objetivos específicos. 2.2.1 Investigación de temas sobre cómputo en paralelo y distribuido. 2.2.2 Investigación sobre los diferentes algoritmos que actualmente se implementan en la

computación en paralelo. 2.2.3 Recopilación de información sobre el modo de uso de la herramienta C#. 2.2.4 Propuesta de diseño del sistema.

Reporte de proyecto terminal 6

3. CÓMPUTO PARALELO

3.1. Arquitecturas paralelas. Para poder entender con mayor claridad el problema que se pretende solucionar fue necesario recabar información sobre los temas de computación en paralelo y computación distribuida. La historia de la computación en paralelo así como la de la computación distribuida se remonta a los inicios de la computación, ya que el paralelismo lo encontramos desde el modelo de BOON NEWMAN.

Dentro de la computación paralela encontramos los siguientes modelos:

• SISD (single instruction stream, single data stream)

Los sistemas de este tipo se caracterizan por tener un único flujo de instrucciones sobre un

único flujo de datos, es decir, se ejecuta una instrucción detrás de otra. Este es el concepto

de arquitectura serie de Von Neumann donde, en cualquier momento, sólo se ejecuta una

única instrucción.

Un ejemplo d

e estos sistemas son las máquinas secuenciales convencionales.

Reporte de proyecto terminal 7

• SIMD(single instruction stream, múltiple date stream)

Estos sistemas tienen un único flujo de instrucciones que operan sobre múltiples flujos de

datos. Ejemplos de estos sistemas los tenemos en las máquinas vectoriales con hardware

escalar y vectorial.

El procesamiento es síncrono, la ejecución de las instrucciones sigue siendo secuencial

como en el caso anterior, todos los elementos realizan una misma instrucción pero sobre

una gran cantidad de datos. Por este motivo existirá concurrencia de operación, es decir,

esta clasificación es el origen de la máquina paralela.

El funcionamiento de este tipo de sistemas es el siguiente. La Unidad de Control manda una

misma instrucción a todas las unidades de proceso (ALUs). Las unidades de proceso operan

sobre datos diferentes pero con la misma instrucción recibida.

Existen dos alternativas distintas que aparecen después de realizarse esta clasificación:

• Arquitectura Vectorial con segmentación:

Una CPU única particionada en unidades funcionales independientes trabajando sobre flujos de datos concretos

• Arquitectura Matricial (matriz de procesadores):

Varias ALUs idénticas a las que el procesador de instrucciones asigna una única instrucción pero trabajando sobre diferentes partes del programa.

Reporte de proyecto terminal 8

Éste modelo a diferencia del anterior es que éste tiene la capacidad de realizar más operaciones a la vez. Por ejemplo la suma A+B la realiza en un solo ciclo de reloj. Lo que se realiza en la suma es los siguiente:

Cada elemento de la suma accesa una de las ALU’s incluyendo el signo (+). Éste ultimo indica que los valores guardados en (A, B) contenidos en algunas de las ALU’s se deberá acumular en alguna otra de las ALU’s y de ésta forma se obtiene la suma en un solo ciclo de reloj.

dentro de esta arquitectura encontramos las siguientes versiones:

1) SIMD CON CPU PARTICIONADA. Ejemplos de estos sistemas los encontramos en CRAY monoprocesador, CYBER 205, FUJITSU, HITACHE, NEC SUPERCOMPUTERS, IBM 390 VF, IBM 9000 VF, ALLIANT FX/1 Y CONVEX.

2) SIMD CON MULTIPLES ALUS

Reporte de proyecto terminal 9

• MISD (múltiple instruction stream, single data stream)

Sistemas con múltiples instrucciones que operan sobre un único flujo de datos. Este tipo de sistemas no ha tenido implementación hasta hace poco tiempo.

Los sistemas MISD se contemplan de dos maneras distintas:

1. Varias instrucciones operando simultáneamente sobre un único dato.

2. Varias instrucciones operando sobre un dato que se va convirtiendo en un

resultado que será la entrada para la siguiente etapa. Se trabaja de forma

segmentada, todas las unidades de proceso pueden trabajar de forma

concurrente.

Ejemplos de estos tipos de sistemas son los arrays sistólicos o arrays de procesadores. También podemos encontrar aplicaciones de redes neuronales en máquinas masivamente paralelas..

• MIMD (múltiple instruction stream, Múltiple data stream)

Son sistemas con un flujo de múltiples instrucciones que operan sobre múltiples datos.

Estos sistemas empezaron a utilizarse a principios de los 80.

Son sistemas con memoria compartida que permiten ejecutar varios procesos

simultáneamente (sistema multiprocesador).

Cuando las unidades de proceso reciben datos de una memoria no compartida estos

sistemas reciben el nombre de MULTIPLE SISD (MSISD).

Reporte de proyecto terminal 10

En arquitecturas con varias unidades de control (MISD Y MIMD), existe otro nivel

superior con una unidad de control que se encarga de controlar todas las unidades de

control del sistema.

Dentro de éste modelo encontramos a las siguientes arquitecturas:

Con memoria compartida. Con memoria distribuida. Con memoria virtual compartida distribuida (DSM).

Algunas de las topologías que se implementan con esta arquitectura son:

Reporte de proyecto terminal 11

una clasificación de las arquitecturas de computación en paralelo según Flynn:

Algunas de las características de la computación en paralelo son:

1. Reducir los tiempos de ejecución de una determinada aplicación. 2. La computación en paralelo trabaja con una sola aplicación a la vez. 3. Una aplicación en paralelo por lo común se divide en varias tareas que se ejecutan

de manera simultánea en más de un procesador. 4. Normalmente las propiedades de un sistema paralelo son homogéneos. (es decir las

características de cada una de las máquinas que conforman el Cluster se procura que tengan las mismas propiedades tanto en HADWARE como en SOFTWARE).

Un buen sistema paralelo debe considerar los siguientes puntos:

1) dividir el trabajo en tareas independientes. 2) Organizar las tareas para tener una adecuada comunicación y sincronización de las

mismas. 3) Asignar las tareas en los nodos adecuados del sistema (es decir las tareas se tratarán

de asignar a aquellos nodos con menos carga de trabajo).

En la división de los trabajos paralelos se habla principalmente de dos tipos de granularidad:

I. GRANULARIDAD FINA.- cuando se realiza la división del trabajo considerando una granularidad fina implica tener pocos cálculos por tarea, y esto implica a la vez muchas comunicaciones entre las tareas.

II. GRANULARIDAD GRUESA.- cuando se lleva a cabo la división de un trabajo considerando una granularidad gruesa implica que cada tarea debe realizar muchos cálculos, lo que implica tener pocas comunicaciones entre las tareas.

Reporte de proyecto terminal 12

La programación en paralelo da origen a la condición de competencia, es decir el mismo programa puede dar distintos resultados si se ejecuta varias veces un proceso con los mismos datos de entrada. La siguiente figura trata de esquematizar ésta situación.

El nacimiento de la computación en paralelo y la computación Distribuida surgen principalmente debido a la necesidad de resolver los siguientes problemas entre otros:

1. Cuando se tiene la necesidad de ejecutar procesos que demandan una gran cantidad de recursos. Recursos que una sola máquina no podría satisfacer. Razón por la cual se tiene que recurrir a la creación de nuevos métodos de programación paralela o distribuida. De ésta forma el proceso se divide en subprocesos que son asignados de forma distribuida en cada uno de los nodos del sistema, y de ésta forma se trata de solucionar dicho problema.

2. Cuando se tiene la necesidad de mejorar los tiempos de ejecución de un proceso. Esto se implementa principalmente en aquellas aplicaciones que requieren que los tiempos de respuesta sean lo más rápido posible. Por ejemplo imagine un buscador en Internet.

3. Cuando se tiene un cúmulo de computadoras que trabajan en conjunto, en este caso se implementa la computación en paralelo o la computación distribuida con la finalidad de aprovechar al máximo los recursos del cúmulo de computadoras, es decir lo que se trata de evitar es que en nuestro cluster existan nodos ociosos mientras otros están saturados, o evitar que existan nodos saturados mientras hayan nodos ociosos.

Básicamente existen dos formas de asignación de tareas dentro de las aplicaciones distribuidas o paralelas, a saber son:

• Asignación dinámica • Asignación Estática.

Reporte de proyecto terminal 13

3.2. Algoritmos para la distribución de cómputo. Algunas de las topologías implementadas en la computación en paralelo son:

los algoritmos orientados a la computación distribuida que se implementados a través de las topologías anteriores son: Algoritmo de tipo global centralizado. Algoritmo de tipo global distribuido. Cíclico. Vecinos directos. Vectorial.

Reporte de proyecto terminal 14

3.3. Recopilación de trabajos similares Los algoritmos que estudiamos son los siguientes: 3.3.1. Algoritmo de tipo global centralizado Gráficamente este algoritmo se representa de la siguiente manera:

Algunas de las características más importantes de este algoritmo son: Uno de los nodos es designado como nodo central (en este caso el nodo4 es designado como nodo central), este nodo central se encarga de mantener disponible en todo momento la información del estado de carga de cada uno de los nodos que conforman la arquitectura del sistema. Con dicha información el nodo central puede visualizar cuales son los nodos con menos carga de trabajo. El nodo que resulte con menos carga es el más propenso a ejecutar un proceso que requiera ser ejecutado. Cuando el estado de carga de algún nodo cambia se debe notificar de inmediato al nodo central, para que éste actualice la información del sistema, de esta forma se garantiza que la información que contienen el nodo central es fidedigna. El nodo central es el único nodo que puede asignar procesos.

Reporte de proyecto terminal 15

3.3.2. Algoritmo de tipo global distribuido Gráficamente este algoritmo se comporta de la siguiente manera:

A diferencia del algoritmo anterior la información de carga del sistema se tienen disponible en cada uno de los nodos que conforman el sistema y no en uno solo. Una de las desventajas de este algoritmo con respecto al anterior es que cuando cambia el estado de carga de alguno de los nodos, este cambio se debe notificar no solo a un nodo sino a todos los nodos que conforman el sistema. Con lo anterior se garantiza que la información sobre el estado de carga del sistema que contenga cada nodo es confiable. Una de las ventajas de este algoritmo con respecto al anterior es que la información del estado de carga del sistema esta distribuida en cada uno de los nodos y por tal motivo todos los nodos tienen la capacidad de asignar procesos.

Reporte de proyecto terminal 16

3.3.3. Cíclico Gráficamente este algoritmo se representa de la siguiente forma:

Como puede observarse, en este modelo no hay necesidad de poseer información respecto al estado de carga del sistema. Como en el caso centralizado, existe un nodo especial el cual determina en base a un orden cíclico, el nodo que ejecutará a un nuevo proceso. Ahora cada vez que un nodo requiere crear un proceso, consulta al nodo especial para saber el procesador donde se ejecutará. Como se considera que la carga se repartirá equitativamente, no se hace necesaria la recolecta de información concerniente al estado de carga actual de los procesadores.

Reporte de proyecto terminal 17

3.3.4. Vecinos directos La representación grafica de este algoritmo se representa en la siguiente figura:

Este algoritmo lo podemos ubicar entre el global centralizado y el global distribuido ya que la información no se concentra en un único nodo como en el caso del algoritmo global centralizado, pero tampoco es cierto que la información que contiene cada nodo sea referente al estado de carga de todos los nodos que conforman al sistema como en el caso del algoritmo global distribuido; la información que contiene cada nodo hace referencia al estado de carga de sus vecinos directos, por ejemplo el nodo 1 contiene únicamente el estado de carga de los nodos 2,4 y por supuesto el estado de carga del propio nodo 1. De esta forma se dice que la información que contiene cada nodo es parcial. Cuando el estado de carga de uno de los nodos cambia, éste debe notificar sobre el cambio de su estado de carga a los nodos que se consideran vecinos directos del nodo cuyo estado de carga ha cambiado. Por ejemplo si el estado de carga del nodo 1 cambia, éste debe notificar sobre el cambio a los nodos 2 y 4 para que estos actualicen la información referente al estado de carga parcial del sistema. En cuanto a la asignación de procesos se dice que todos los nodos lo pueden llevar a cabo con la condición de que el nodo que asigne un proceso lo haga únicamente a uno de los nodos que sean vecinos directos del nodo asignador. Por ejemplo el nodo 1 puede asignar procesos únicamente a los nodos 1,2 y 4.

Reporte de proyecto terminal 18

3.3.5. Vectorial La representación grafica de este algoritmo se muestra en la siguiente figura:

Se asigna a cada nodo i un vector L conteniendo el estado de carga de m nodos: L[0],L[1],L[2],...L[m-1], m<n, donde n es el número total de nodos en el sistema. El primer elemento de L es el estado de carga local del nodo i y el resto son los estados de carga de otros m-1 nodos arbitrarios. Para cada nodo i, cuando ocurre un cambio en su estado de carga local, el vector es actualizado de la siguiente manera siguiendo un método aleatorio:

1. Se actualiza en L la carga propia del nodo i (L[0]) 2. Se elige al azar un nodo j y se le envía la primera mitad del vector L. 3. Cuando el nodo j recibe la mitad del vector, modifica su propio vector L

intercalando en las posiciones impares (L[1], L[3], L[5],..) de su vector los valores recibidos.

En base a esta información parcial (vector), cada procesador del sistema es capaz de decidir el sitio donde asignará un proceso. A manera de ejemplo, si se tienen 2 nodos (i y j) con los vectores respectivos Li y Lj siguientes:

L j (antes de actualización):

Reporte de proyecto terminal 19

Si el nodo i requiere hacer una actualización de su estado de carga de Normal a Descargado, modifica el primer elemento de su vector Li[0] y elige aleatoriamente a un nodo j para enviarle la primer mitad de Li. Al recibir dicha información, el nodo j la intercala en su propio vector Lj como se muestra a continuación. L j (después de actualización):

Después de haber presentado las características de algunos algoritmos básicos para la asignación dinámica de procesos y para favorecer el estudio y aplicación de estas técnicas, se desarrolló una plataforma que será expuesta con mayor detalle en el siguiente capítulo.

Reporte de proyecto terminal 20

4. INTRODUCCIÓN AL LENGUAJE DE PROGRAMACIÓN C#

4.1. Estudio de la plataforma .NET. Uno de los propósitos de nuestro trabajo de investigación es el determinar si a través de la herramienta C# se pueden ejecutar procesos de forma paralela. Por lo cual fue necesario investigar todo lo posible sobre este lenguaje de programación. Esta parte de nuestro trabajo cubre los siguientes puntos: 4.1.1. Introducción a la plataforma .NET. .NET Es un paquete de desarrollo diseñado por Microsoft, ésta plataforma tiene como finalidad simplificar las aplicaciones para Internet. Ésta plataforma esta constituida principalmente por los siguientes componentes:

Una máquina virtual que procesa código escrito en un lenguaje intermedio (MSIL: Microsoft Intermediate Lenguaje). Una biblioteca que contiene todas las clases (biblioteca .NET). ASP.NET que proporciona los servicios necesarios para crear aplicaciones WEB. JIT(Just in Time) es el compilador mediante el cual se traduce el lenguaje

intermedio. Dentro de ka plataforma .NET encontramos los siguientes lenguajes de programación:

Visual Basic. C Sharp (C#). C/C++. J#. Cristal Reports.

C Sharp (C#) .- Es un lenguaje de alto nivel. Básicamente C# es una evolución de C/C++. Mediante C# se pueden escribir programas normales, pero además podemos escribir programas para Internet.

Una de las cualidades de .NET es que cada uno de los lenguajes de programación contenidos en la plataforma tienen un compilador (programa traductor) que produce un código intermedio. Éste código intermedio es el que la máquina virtual ejecutara. Es decir cada lenguaje de la plataforma contiene un compilador que produce código correspondiente a un único lenguaje que en éste caso es el MSIL. En el siguiente grafico se muestra lo explicado anteriormente.

Reporte de proyecto terminal 21

El lenguaje MSIL es un lenguaje independiente de las arquitecturas de los procesadores, es decir el código MSIL es un lenguaje nativo de la máquina virtual de .NET. La tarea encomendada al compilador JIT es el de producir código nativo para el microprocesador particular de nuestra máquina. De lo expuesto anteriormente se concluye que una de las ventajas significativas de C# con respecto a otros lenguajes de programación es que el código generado en C# es independiente de la plataforma (en general podemos decir lo mismo de los demás programas contenidos en .NET) es decir el código producido por C# puede ser transportado a cualquier plataforma (Intel, Sparc, Motorola, etc). La única condición que se pide es tener instalado el paquete .NET. 4.1.2. Instalación del lenguaje de programaciónC#. Antes que nada consideramos importante mencionar la forma de obtener la herramienta .NET y de indicarle lo básico al usuario.

1. Una manera de obtener .NET es adquiriendo la licencia de la misma. 2. Otra de las formas de obtener .NET es consultando la siguiente dirección de

Internet: http://msdn.microsoft.com. En ésta dirección podemos conseguir de forma gratuita el Framework SDK.

en esta dirección de Internet encontrara un archivo como el de la figura de arriba. Para instalar el Framework SDK bastara con dar doble clic sobre el archivo y la instalación se iniciará.

Reporte de proyecto terminal 22

en la misma dirección de Internet encontrara dos archivos como los de la figura de anterior. Estos archivos los debe contemplar el usuario ya que en ellos esta contenido la ayuda de la plataforma .NET. una vez que se hayan instalado los archivos anteriores se debe realizar lo siguiente para indicarle al sistema operativo de la ubicación de la utilidad de csc (C Sharp compiler). El usuario debe abrir una ventana de línea de comandos en la que deberá escribir lo siguiente:

ahora si nuestro entorno de desarrollo esta listo para poder crear y ejecutar programas en C#. (se indica la usuario que los archivos antes mencionados fueron instalados en maquinas con Windows XP profesional versión 5.1) 4.1.3. Creación de un programa en C#. En este punto se indica al usuario la manera de crear un programa a través de la herramienta C# desde la línea de comandos. A manera de ilustración indicamos al lector la forma de crear el típico programa hola mundo. Para editar el programa podemos utilizar cualquier editor de texto guardando el documento con extensión .CS (ejemplo: HolaMundo.cs ).

Reporte de proyecto terminal 23

Por ejemplo el siguiente programa está creado implementando el bloc de notas

4.1.4. Compilación y ejecución de un programa creado en C#. A través de la compilación lo que se hace es traducir el programa fuente a código intermedio MSIL(Microsoft Intermediate Language) para posteriormente poder ejecutarlo. Para compilar el programa anterior desde la línea de comandos el usuario debe realizar lo siguiente:

a) Abrir una ventana de línea de comandos(implementando cmd o command). b) Indicarle al sistema operativo la ubicación de las utilidades del compilador

de C# (csc) mediante las siguientes instrucciones: path=%path%;C:\WINNT\Microsoft.NET\Framework\v1.0.2914 c) Mediante el comando cd nos colocamos en la ruta donde se encuentra

nuestro archivo HolaMundo.cs (por ejemplo cd c:\Escritorio\HolaMundo.cs) d) Mediante el comando dir podemos comprobar que realmente nos

encontramos en la dirección donde se encuentra nuestro archivo.

e) Ahora si estamos en condiciones de compilar nuestro archivo, y esto lo realizamos mediante las siguientes instrucciones: csc HolaMundo.cs + ENTER.

Reporte de proyecto terminal 24

El resultado de la compilación es un archivo con extensión .exe. En éste caso debemos obtener un archivo llamado HolaMundo.exe

Es importante hacerle saber al usuario que el compilador de C# hace diferencias entre las letras minúsculas y las mayúsculas. Por ejemplo si se escribe en el programa fuente String en lugar de string. El compilador nos enviará el siguiente error:

f) Para poder ejecutar nuestro programa HolaMundo.cs lo que debemos hacer

es lo siguiente: en una pantalla de línea de comandos colocarnos en el directorio donde se encuentra el archivo que contiene el código fuente, una vez hecho lo anterior escribimos en la línea de comando el nombre del archivo del programa en nuestro caso HolaMundo. El resultado que obtenemos es el siguiente:

Reporte de proyecto terminal 25

si no nos colocamos en el directorio donde se encuentra el archivo que contiene el programa entonces a la hora de querer ejecutar el programa obtendremos el siguiente error:

4.1.5. Inclusión de librerías para que un programa pueda ser compilado exitosamente. Por omisión el compilador de C# solo busca librerías predefinidas en el fichero mscorlib.dll de la biblioteca .NET por lo tanto cuando sea necesario utilizar librerías guardadas en otros ficheros habrá que utilizar la opción /r para especificarlos. Por ejemplo csc /r:System.Management.dll HolaMundo.cs Con la instrucción /r se anexan todas las librerías que requiera un programa fuente para que éste pueda ser compilado exitosamente. Nota: Para poder depurar un programa en C# lo hacemos con la instrucción csc / debug HolaMundo.cs Mediante la instrucciones csc /t:library le indicamos al compilador que el tipo de archivo que se debe generar es uno con extensión .dll en lugar de uno con extensión .exe, el archivo generado con extensión .dll puede ser implementado posteriormente a la hora de compilar otro archivo que requiera de las propiedades guardadas en el archivo con extensión .dll 4.1.6. Análisis de C# para ejecutar procesos en paralelo. Como ya mencionamos en la introducción, uno de los propósitos de nuestro trabajo de investigación fue el determinar si a través del lenguaje de programación C# se podían implementar procesos que fueran ejecutados de forma paralela. Después de introducirnos en el lenguaje de programación C# encontramos información sobre una clase que nos indicaba que podía ser posible implementar comunicación entre dos a más maquinas que estuvieran conectadas en red. Esta clase se llama TcpClient.

Las tareas de la clase TcpClient son solicitar datos de un recurso de Internet utilizando TCP. Los métodos y propiedades de TcpClient toman los detalles de creación de una instancia de Socket para solicitar y recibir datos mediante el uso de un protocolo TCP.

Reporte de proyecto terminal 26

Dado que la conexión al dispositivo remoto se representa como una secuencia, se pueden leer y escribir datos con técnicas de control de secuencias de .NET Framework.

El protocolo TCP establece una conexión con un extremo remoto y después utiliza dicha conexión para enviar y recibir paquetes de datos. TCP se encarga de garantizar que los paquetes de datos se envíen al extremo y se ensamblen en el orden correcto cuando lleguen.

Para establecer una conexión TCP, se debe conocer la dirección del dispositivo de red que aloja el servicio que se necesita así como el puerto TCP que el servicio utiliza para la comunicación. Internet Assigned Numbers Authority (IANA) define los números de puerto para servicios comunes (vea http://www.iana.org/assignments/port-numbers). Los servicios no incluidos en la lista de IANA pueden tener números de puerto en el intervalo comprendido entre 1,024 y 65,535. Una vez que se tuvo conocimiento de la clase TcpClient empezamos a realizar pruebas de comunicación entre dos maquinas conectadas en red obteniendo como resultado una comunicación rápida y satisfactoria en cuanto a los datos que se esperaban. De esta forma se determino que dos o mas maquinas pueden comunicarse remotamente a través de las herramientas que nos ofrece el lenguaje de programación C#. Dedo que uno de los factores principales de la computación en paralelo es poder comunicarse con cada una de las maquinas del cluster, se determina que si es posible ejecutar procesos en paralelo implementando el lenguaje de programación C#. 4.2. Inicialización del ambiente de trabajo. En este punto se realizo todo lo necesario para iniciar a trabajar con C#. Los puntos que se cubrieron en esta parte de nuestro trabajo de investigación fueron los siguientes:

a) Bajar de Internet los paquetes SETUP.EXE, NDP10_SP_1.EXE, NDP10_SP_2.EXE. el primer paquete nos sirve para instalar el lenguaje de programación C#, los dos restantes los empleamos para instalar la ayuda de C#.

b) Instalar cada uno de los paquetes anteriores.

c) Indicar la ruta de la carpeta donde se almacenan las utilidades de C#. Esto ultimo lo

conseguimos a través de la siguiente línea: Path=%path%;C:\WINNT\Microsoft.NET\Framework\v1.0.2914 Una vez realizados estos pasos nuestro entorno de trabajo esta listo para ser utilizado en cualquier momento.

Reporte de proyecto terminal 27

5. PROPUESTA DE DISEÑO DE UNA APLICACIÓN PARALELA CON C#.

Después de haber estudiado los alcances que podemos obtener de C# y de haber estudiado los algoritmos y metodologías que se emplean en la computación en paralelo, pudimos iniciar el planteamiento de nuestra propuesta. En nuestra propuesta contemplamos toda la información obtenida para ofrecer una propuesta lo más optima posible tanto en tiempos como en rendimiento de los recursos. El método de programación que adoptamos fue la programación orientada a objetos (POO). Nuestro sistema está estructurado en base a módulos(clases). cada módulo tiene una función especifica e indispensable para que nuestro sistema funcione adecuadamente. todos los módulos se consideran de carácter funcional, es decir que para que el sistema pueda funcionar adecuadamente es necesario que cada uno de estos módulos este presente en cada uno de los nodos que conformen el cluster y que además funcione adecuadamente. Las peticiones remotas las realizamos a través del medio de comunicación TCP. La propuesta de nuestro diseño contempla el método de cuantificación de carga unitaria. Se pretende que el sistema a desarrollar tenga la capacidad de ser MULTI-USUARIO El método que propusimos para obtener el estado de carga de nuestro sistema le llamamos barrido de nodos. 5.1. Identificación de módulos del sistema. Durante la fase de análisis y diseño del sistema se determino que la estructura de cada nodo debe estar conformado por los siguientes módulos:

TrackingHandler.cs ServiceClass.cs Server.cs mAsignador.cs Client.cs

Llamamos módulos funcionalmente independientes a aquellas clases que no llaman a ni una otra clase durante su ejecución:

TrackingHandler.cs ServiceClass.cs

Le llamamos módulos funcionalmente dependientes a aquellas Clases que invocan a alguna de las clases antes mencionadas durante su ejecución:

mAsignador.cs (invoca las clases ServiceClass.cs, MiServiceClass.cs) Client.cs (invoca las clases ServiceClass.cs, mAsignador.cs) Server.cs (invoca las clases ServiceClass, TrackingHandler.cs)

Reporte de proyecto terminal 28

En la planeación de nuestro sistema se determino que los únicos módulos que deberían contener puntos de entrada y salida a nuestra aplicación (contienen una función main()) son:

• Client.cs • Server.cs

5.2. Propuesta de la arquitectura del sistema.

La arquitectura del sistema que proponemos se muestra en la siguiente figura:

Clien t mAsignador

Solicitud de evento: Ordenar o introducir datos

Busca_Nodo_Menos_Cargado()

Visita_Maquina_Local()

ServiceClass

getDate()

Visita_Maquina1()

Hay conexion con Maquina1

Genera conexion con maquina k

ServiceClass

getDate()

Visita_Maquinak()

Hay conexion con Maquina k

Genera conexion con maquina k

ServiceClass

getDate()

Maquina con menos carga =Maquina local

Ejecuta accion:Ordenar o int roducir datos

Despliega resultados en pant alla

el usuario quiere cont inuar en el sistema

f in aplicacion Client

se crea el cana a t raves del cual s e lleva ra la c omun icac ion

Hay conexion con maquina con menos carga de t rabajo

se realiza la conexion con la maquina con men os car ga de tr abajo

.ServiceClass

_ServiceClass

Ejecuta accion: Ordenar o int roducir datos

si

no

no

si

no [Termina la aplicacion Client ]

si

Regresa % CPU

Genera Objeto

Verif ica Maquina local

regresa % CPU en uso

no

si

crea objeto

Obt iene % CPU

regresa % CPU

Obt iene % CPU

Regresa % CPU

Regresa % CPU

regresa % CPU en uso

ver if ica m aq uina 1

Obt iene % CPURegresa % CPU

no

si

crea objeto

Regresa % CPU

verif ica maquina k

regresa % CPU en uso

Regresa direccion de maquina con menos carga de t rabajo

busca maquina con menos carga de t rabajo

regresa maquina con menos carga de t rabajodetermina a que maquina redireccionar la pet icion

realiza la coneccion

crea el objeto

ejecuta la pet icion

envia los resultados a la maquina que recibio la pet icion

ejecuta la pet icion

5.3. Funcionalidad de los módulos.

Módulo Cliente Mediante ésta clase se inicializa la aplicación del cliente. Una vez que se ejecuta este módulo el sistema esta en espera de que algún usuario le haga una petición. Un prerrequisito para que este módulo pueda atender peticiones de usuarios es que se ejecute el módulo Server.cs, si el módulo Server.cs no se ejecuta las peticiones de los usuarios no podrán ser atendidas.

Reporte de proyecto terminal 29

En este módulo se encuentran catalogadas todas las funcionalidades que el sistema puede ofrecer al usuario. Las funcionalidades que nuestro sistema ofrece al usuario son:

3) INSERCIÓN DE DATOS. 4) ORDENAMIENTO DE DATOS.

De igual forma es en este módulo donde se encuentran las opciones de:

1) CONTINUAR EN EL PROGRAMA 2) SALIR DE LA APLICAION.

Además en este módulo se crea un objeto de la clase(módulo) mAsignador a través de este objeto se realiza la búsqueda del nodo con menos carga dentro de nuestro cluster. El nodo que se determine con menos carga es el candidato para ejecutar la próxima petición que llegue al sistema.

Módulo Server Una de las cualidades de este módulo es que en todo momento está en espera de peticiones remotas o locales. a través de éste módulo se lleva a cabo la atención de las peticiones que le llegan al sistema de ejecutar procesos remotamente. De acuerdo al diseño de nuestro sistema cuando se asigna un proceso remotamente es por que previo a esto se averiguo sobre la carga de trabajo de cada uno de los nodo que conforman el cluster sobre el que se este trabajando, el proceso se asigna al nodo con menos carga de trabajo. La forma en como se comunican los nodos interesados en el proceso es mediante los módulos ServiceClass y TrackingHandler.

mAsignador A través de este módulo se pone en practica el algoritmo que propusimos para determinar el estado de carga de cada uno de los nodos que se encuentran disponibles para poder llevar a cabo las peticiones que le lleguen a nuestro sistema. A través de este módulo se lleva a cabo el barrido de los nodos y se determina cual es el que tiene menos carga de trabajo, una vez que se determina el nodo con menor carga de trabajo se le asigna a éste el proceso que se requiera ejecutar. Este módulo es invocado por el módulo Client quien a su vez es quien recibe las peticiones de crear nuevos procesos o de ejecutar procesos ya existentes. Una vez que el módulo Client sabe que nodo tiene menos carga de trabajo redirecciona la petición que le llego hacia el nodo que resulto con menos carga de trabajo.

Reporte de proyecto terminal 30

ServiceClass La clase ServiceClass hereda de MarshalByRefObject que es a su vez una de las clases que nos ofrece la plataforma .NET. debido a la herencia que existe entre estas dos clases se asegura que la clase ServiceClass puede utilizar todas las funciones de la clase MarshalByRefObject pero además se pueden definir en la clase ServiceClass funciones locales a ésta. En este módulo (ServiceClass) se coloca todo el código necesario para que se pueda llevar a cabo cada una de las funciones que ofrece nuestro sistema. Por ejemplo: 1. En este módulo se coloca el código necesario para que se pueda llevar a cabo la búsqueda del nodo con menos carga. 2. En éste módulo se coloca el código necesario para que se pueda llevar a cabo la acción de insertar datos o de ordenar a los mismos.

TrackingHandler

Al igual que el módulo anterior la clase TrackingHandler es una subclase de la clase ItrackingHandler por lo que la clase TrackingHandler hereda todas las propiedades de la clase ItrackingHandler, pero además de estas propiedades podemos definir nuestros propios atributos y funciones locales de nuestro módulo. Mediante esta clase se realizan todas las acciones de notificación al objeto que realiza la implementación el cálculo de referencias, la resolución de referencias y la desconexión de objetos y servidores proxy mediante la infraestructura remota. Es decir que con la ayuda de esta clase se entabla la conexión entre dos o más máquinas para poder llevar a cabo acciones empleando comunicación remota.

Reporte de proyecto terminal 31

5.4. Definición de casos de uso. Caso de uso Client

CU1-CLIENT

PROYECTO:

Sistema balanceador de carga FECHA: 12/ Septiembre / 2004

AUTOR: Javier Pérez Barilla CLAVE: CU1 NIVEL ALCANCE Resumen muy general Organización (caja negra) Resumen x Organización (caja blanca) Actividad de usuario Módulo X Detalle Método

DESCRIPCIÓN BREVE Mediante el módulo Client se inicializa todo lo necesario para que el usuario del sistema pueda hacer peticiones al sistema.

ACTORES Actor principal Usuario del sistema. Actores secundarios

EVENTOS QUE LO INICIAN 1 Ejecutar el módulo Client. 2 El usuario debe seleccionar una de las opciones que le ofrece el sistema.

FLUJO DE EVENTOS PRIMARIO 1 Ejecutar el módulo Client 2 El sistema despliega el menú de sus aplicaciones, y le pide al usuario que seleccione

una de ellas. 3 El usuario selecciona una de las opciones y presiona enter. (si se ha introducido algo

diferente a las opciones que le ofrece el sistema automáticamente ejecuta una acción que se establece como acción por default)

4 El sistema averigua cual es el nodo con menos carga. 5 El sistema determina la dirección del host al que se redireccionará la petición de

ejecutar un determinado proceso. 6 El sistema envía el proceso a ejecutar al host que tiene la dirección que se formo en el

punto anterior. (si el proceso se ejecuta remotamente, entonces antes se entabla la conexión con el host al cual se le envía el proceso a ser ejecutado).

7 El sistema ejecuta el proceso localmente o remotamente. 8 El sistema obtiene los resultados del proceso ejecutado. 9 El sistema despliega los resultados obtenidos en el host donde se solicito la ejecución

Reporte de proyecto terminal 32

del proceso. 10 El sistema le pide al usuario que indique si quiere seguir en la aplicación o si quiere

salir de la misma. 11 El usuario indica la siguiente acción a ejecutar. (si se desea continuar el sistema

regresa al punto 2). 12 Fin.

FLUJO DE EVENTOS ALTERNATIVOS 1 El usuario introduce una opción no ofrecida por el sistema. 2 El usuario introduce datos no validos para la ejecución de su petición. 3

PRECONDICIONES 1 Ejecutar el módulo Client. 2 Exista un usuario interesado en hacer uso del sistema.

POSCONDICIONES 1 Desplegar los datos obtenidos como resultado de la ejecución de una aplicación a

través del sistema. 2 Indicarle al sistema cual va a ser la siguiente acción a ejecutar.

Navegación de Pantallas Client Es importante hacer mención que en realidad no se manejan diferentes pantallas, sino más bien son instancias de una misma pantalla pues le hacemos recordar que la aplicación de nuestro sistema se realizo implementando un entorno de línea de comandos y no un entorno grafico.

Edo. Inicial

Menu de Aplicaciones

Introduce Datos

Ordena Datos

Indica Siguiente Accion a Ejecutar

Edo. Final

Selecciona Opcion Introducir Datos

Selecciona Ordenar Datos

Despues de Ejecutar el Proceso

Despues de Ejecutar el Proceso

El usuario determino salir de la aplicaión

El usuario determino seguir en la aplicación

Reporte de proyecto terminal 33

Caso de uso Server

CU2.- SERVER

PROYECTO:

Sistema balanceador de carga FECHA: 18 / Septiembre / 2004

AUTOR: Javier Pérez Barilla CLAVE: CU2 NIVEL ALCANCE Resumen muy general Organización (caja negra) Resumen x Organización (caja blanca) Actividad de usuario Módulo X Detalle Método

DESCRIPCIÓN BREVE Mediante el módulo Server se atienden todas aquellas peticiones que le llegan al nodo que funge como nodo Servidor.

ACTORES Actor principal Administrador del sistema. Actores secundarios

EVENTOS QUE LO INICIAN 1 Ejecutar la clase Server. 2 El usuario realice peticiones al sistema, y estos se realicen remotamente.

FLUJO DE EVENTOS PRIMARIO 1 Ejecutar el módulo Server. 2 El sistema crea el canal de comunicación a través del cual se le podrán hacer

peticiones. 3 El sistema registra el canal antes creado para que se puedan llevar a cabo las

comunicaciones remotas a través de éste. 4 El sistema está en espera de que le lleguen peticiones. 5 El sistema ejecuta la petición que le llego y devuelve los resultados al host que le

hizo la petición. 6 El sistema regresa al punto 4. 7 Fin. 8 9 10 11

Reporte de proyecto terminal 34

FLUJO DE EVENTOS ALTERNATIVOS 1 Se rompe el canal de comunicación a través del cual se entablo la comunicación. 2 Llega una petición que no se encuentra definida dentro de la clase ServiceClass.

PRECONDICIONES 1 Ejecutar el módulo Server. 2 Crear un canal de comunicación a través del cual se podrán recibir las peticiones que

le lleguen.

POSCONDICIONES 1 Regresar los resultados de ejecutar el proceso que se pidió ejecutará. 2 Cerrar el canal de comunicación a través del cual se escuchaban las peticiones.

Navegación de pantallas Server Es importante hacer mención que en realidad no se manejan diferentes pantallas, sino más bien son instancias de una misma pantalla pues le hacemos recordar que la aplicación de nuestro sistema se realizo implementando un entorno de línea de comandos y no un entorno grafico.

Edo Inicial (despues de ejecutar Server.cs)

Pantalla Inicial (Espera Peticiones)

Atiende Peticiones

Edo. Final (se termina la ejecucion de la clase Server.cs)

Regresa resultados al Host que le hizo la peticion / [y vueve a esperar asta que le llega otra peticion]

llega una peticion

Reporte de proyecto terminal 35

5.5. Estructuración de cada módulo.

Cliente.cs La estructura de este módulo es el siguiente: public static void Main(string[] Args) Esta función es el punto de entrada y salida de nuestro módulo Client. Dentro de esta función se crean objetos de las clases ServiceClass() y de la clase mAsignador(); el objeto creado de la clase mAsignador() lo empleamos para determinar cual es el host con menos carga de trabajo dentro de nuestro sistema, una vez que se conoce esta información entonces podemos direccionar la ejecución de un proceso hacia este nodo (nodo con menos carga de trabajo). El objeto creado de la clase ServiceClass() lo empleamos para que el nodo que resulte con menos carga de trabajo sepa a que clase acudir para obtener el código necesario para que éste pueda ejecutar la petición que le haya llegado. La ejecución del proceso se puede realizar localmente o remotamente, en ambos casos se emplea el objeto de la clase ServiceClass(). Además en esta clase se determina cual es la acción que quiere ejecutar el usuario (introducir datos, u organizarlos). En ésta clase también se determina si el usuario quiere seguir en la aplicación o si desea salir de la misma.

Server.cs El contenido de éste módulo es el siguiente: public static void Main(string[] Args) Mediante esta función iniciamos y terminamos la aplicación de este módulo. Dentro de esta función creamos un objeto de la clase TcpChannel(IP). Mediante este objeto creamos el canal de comunicación a través del cual escuchara las peticiones que le lleguen. A este objeto se le pasa el parámetro IP, esta dirección IP indica a través de que canal está disponible para atender peticiones. Además se crea un objeto de la clase ServiceClass() mediante el objeto creado de esta ultima clase se asegura que el servidor acepte únicamente peticiones que estén contenidas dentro de la clase ServiceClass(). Para que se puedan ejecutar procesos en paralelo es indispensable que esta clase esté en ejecución, de lo contrario las peticiones no podrán ser atendidas.

Reporte de proyecto terminal 36

mAsignador Este módulo está estructurado de la siguiente forma: Dentro del constructor de la clase mAsignador se manda llamar a la función public void Inicializa_Direcciones(). Como su nombre lo indica con esta función se inicializan las direcciones de cada uno de los host que actúan en nuestro sistema. Dentro de este módulo también encontramos a la función public int Busca_Nodo_Menos_Cargado() función con la que se determina cual es el nodo con menos carga de trabajo, con base a esta información se determina a que nodo enviar la petición de ejecutar un proceso. Para saber que nodo tiene menos carga se emplea el algoritmo que se propuso y que llamamos Barrido de Nodo. Ésta última función se auxilia de las siguientes funciones para poder obtener el nodo con menos carga de trabajo: public int Maquina_Local() dentro de esta función se crea un objeto de la clase ServiceClass() y accesamos a su función local getDate función con la cual averiguamos cual es la carga de trabajo de la máquina local. public int Visita_Maquina1(string Dir) con esta función se determina cual es la carga de trabajo de la máquina1, a esta función se le pasa el parámetro Dir que indica la dirección IP de la máquina a la cual deberá averiguar su carga de trabajo. La forma de obtener la carga de trabajo de esta máquina es muy similar al proceso que realiza la maquina local. . . . public int Visita_Maquina_N(string Dir) con esta función se determina cual es la carga de trabajo de la máquina_N. a esta función se le pasa el parámetro Dir que indica la dirección IP de la máquina a la cual deberá averiguar su carga de trabajo. La forma en como obtiene su carga de trabajo de ésta máquina es muy similar al proceso que realiza la maquina local. Así mismo dentro de este módulo encontramos la función public void Actualiza_Conexiones() con la que se cambia de estado una conexión de falso a verdadero o viceversa.

ServiceClass La estructura de este módulo es el siguiente: Esta clase es una subclase de la clase MarshalByRefObject() por lo que hereda todas las funciones de ésta ultima. Dentro de los métodos públicos que hereda encontramos a: CreateObjRef Crea un objeto que contiene toda la información relevante necesaria para generar un proxy utilizado para comunicarse con un objeto remoto.

Reporte de proyecto terminal 37

Equals (se hereda de Object) Determina si dos instancias de Object son iguales. GetHashCode (se hereda de Object) Sirve como función hash para un tipo concreto, apropiado para su utilización en algoritmos de hash y estructuras de datos como las tablas hash. GetLifetimeService Recupera el objeto de servicio de duración actual que controla la directiva de duración de esta instancia. GetType (se hereda de Object) Obtiene el objeto Type de la instancia actual. InitializeLifetimeService Obtiene un objeto de servicio de duración para controlar la directiva de duración de esta instancia. ToString (se hereda de Object) Devuelve un objeto String que representa al objeto Object actual. Dentro de los métodos protegidos encontramos a: Finalize (se hereda de Object). Permite que un objeto Object intente liberar recursos y realizar otras operaciones de limpieza antes de que el objeto Object sea reclamado por el recolector de elementos no utilizados. En C# y C++, los finalizadores se expresan mediante la sintaxis del destructor. MemberwiseClone (se hereda de Object) Crea una copia superficial del objeto Object actual. Además de las funciones que hereda encontramos las funciones que se definen localmente como son: public DateTime GetServerTime() función con la que se obtiene la fecha y hora del sistema public int getDate() función con la que se obtiene(simula) el % de uso del procesador de una determinada máquina (cabe mencionar que éste valor lo generamos aleatoriamente). public void IntroduceDatos() función con la que se pide al usuario que introduzca datos. public void OrdenaDatos() función con la que se ordenan los datos introducidos(si los hay). en este caso se emplea el método de la burbuja para realizar el ordenamiento de los datos

Reporte de proyecto terminal 38

TrackingHandler El contenido de este módulo es el siguiente: Este módulo es una subclase de la clase ItrackingHandler() por lo que nuestro módulo hereda todas las propiedades de ésta ultima clase. Dentro de las clases publicas que hereda encontramos a: DisconnectedObject Notifica a la instancia actual que se ha desconectado un objeto de su proxy. MarshaledObject Notifica a la instancia actual que ya se han calculado las referencias de un objeto. UnmarshaledObjectT Notifica a la instancia actual que ya se han resuelto las referencias de un objeto. Además de las funciones heredadas encontramos las funciones propias de la subclase TrackingHandler() como son: private void DumpChannelInfo(IChannelInfo info)

Reporte de proyecto terminal 39

6. OBJETIVOS Y METAS ALCANZADOS.

Se concluye que los objetivos alcanzados son los siguientes: 6.1. Investigación de temas sobre cómputo en paralelo y distribuido. La información recabada sobre este punto nos ayudo a tener una visión mas clara de los objetivos que se persiguen al implementar un sistema que tenga la capacidad de ejecutar procesos en paralelo. Debido a lo anterior se considera que este objetivo se cubrió satisfactoriamente. 6.2. Investigación sobre los diferentes algoritmos que actualmente se implementan en

la computación en paralelo. El contenido informático de estos temas nos sirvió para tener un punto de referencia sobre los algoritmos y las arquitecturas que se implementan para este tipo de sistemas. Con base a la información contenida en este punto fue como pudimos proponer la arquitectura y el algoritmo para determinar el estado de carga de nuestro sistema. Por lo anterior se concluye que este punto se cubrir totalmente de forma satisfactoria. 6.3. Recopilar información sobre el modo de uso de la herramienta C#. Uno de los objetivos de nuestro trabajo de investigación fue el determinar si a través de la herramienta C# se podían construir sistemas como el de nuestra propuesta. Debido a que todo el código que se empleo para la construcción del sistema se realizo con C# se concluye que este punto se cubrió en su totalidad. 6.4. Propuesta de diseño. A través de toda la información recabada pudimos dar inicio al planteamiento de nuestras ideas, iniciando por la identificación de las funcionalidades que se requerían obtener del sistema, una vez que se identificaron estas funcionalidades se dio inicio a la construcción de la arquitectura que debía tener nuestro sistema. 6.5. Crear un programa de cómputo que tenga la capacidad de balancear la carga de

trabajo en un conjunto de computadoras conectadas en paralelo. Este punto se cubrió en su totalidad ya que nuestro trabajo de investigación concluye con la creación de un sistema balanceador de carga. El software que se empleo fue C# de la plataforma .NET.

Reporte de proyecto terminal 40

7. RESULTADOS.

Los resultados obtenidos de nuestro trabajo de investigación son los siguientes:

1) propuesta de la arquitectura del sistema.

Clien t mAsignador

Solicitud de evento: Ordenar o int roducir datos

Busca_Nodo_Menos_Cargado()

Visita_Maquina_Local()

ServiceClass

getDate()

Visita_Maquina1()

Hay conexion con Maquina1

Genera conexion con maquina k

ServiceClass

getDate()

Visita_Maquinak()

Hay conexion con Maquina k

Genera conexion con maquina k

ServiceClass

getDate()

Maquina con menos carga =Maquina local

Ejecuta accion:Ordenar o introducir datos

Despliega resultados en pant alla

el usuario quiere cont inuar en el sistema

f in aplicacion Client

se crea el cana a t raves del cual s e lleva ra la c omun icac ion

Hay conexion con maquina con menos carga de t rabajo

se realiza la conexion con la maquina con men os car ga de tr abajo

.ServiceClass

_ServiceClass

Ejecuta accion: Ordenar o int roducir datos

si

no

no

si

no [Termina la aplicacion Client ]

si

Regresa % CPU

Genera Objeto

Verif ica Maquina local

regresa % CPU en uso

no

si

crea objeto

Obt iene % CPU

regresa % CPU

Obt iene % CPU

Regresa % CPU

Regresa % CPU

regresa % CPU en uso

ver if ica m aq uina 1

Obt iene % CPURegresa % CPU

no

si

crea objeto

Regresa % CPU

verif ica maquina k

regresa % CPU en uso

Regresa direccion de maquina con menos carga de t rabajo

busca maquina con menos carga de t rabajo

regresa maquina con menos carga de t rabajodetermina a que maquina redireccionar la pet icion

realiza la coneccion

crea el objeto

ejecuta la pet icion

envia los resultados a la maquina que recibio la pet icion

ejecuta la pet icion

Reporte de proyecto terminal 41

2) diseño de casos de uso.

Caso de uso Client

CU1-CLIENT

PROYECTO:

Sistema balanceador de carga FECHA: 12/ Septiembre / 2004

AUTOR: Javier Pérez Barilla CLAVE: CU1 NIVEL ALCANCE Resumen muy general Organización (caja negra) Resumen x Organización (caja blanca) Actividad de usuario Módulo X Detalle Método

DESCRIPCIÓN BREVE Mediante el módulo Client se inicializa todo lo necesario para que el usuario del sistema pueda hacer peticiones al sistema.

ACTORES Actor principal Usuario del sistema. Actores secundarios

EVENTOS QUE LO INICIAN 1 Ejecutar el módulo Client. 2 El usuario debe seleccionar una de las opciones que le ofrece el sistema.

FLUJO DE EVENTOS PRIMARIO 1 Ejecutar el módulo Client 2 El sistema despliega el menú de sus aplicaciones, y le pide al usuario que seleccione

una de ellas. 3 El usuario selecciona una de las opciones y presiona enter. (si se ha introducido algo

diferente a las opciones que le ofrece el sistema automáticamente ejecuta una acción que se establece como acción por default)

4 El sistema averigua cual es el nodo con menos carga. 5 El sistema determina la dirección del host al que se redireccionará la petición de

ejecutar un determinado proceso. 6 El sistema envía el proceso a ejecutar al host que tiene la dirección que se formo en el

punto anterior. (si el proceso se ejecuta remotamente, entonces antes se entabla la conexión con el host al cual se le envía el proceso a ser ejecutado).

7 El sistema ejecuta el proceso localmente o remotamente. 8 El sistema obtiene los resultados del proceso ejecutado.

Reporte de proyecto terminal 42

9 El sistema despliega los resultados obtenidos en el host donde se solicito la ejecución del proceso.

10 El sistema le pide al usuario que indique si quiere seguir en la aplicación o si quiere salir de la misma.

11 El usuario indica la siguiente acción a ejecutar. (si se desea continuar el sistema regresa al punto 2).

12 Fin.

FLUJO DE EVENTOS ALTERNATIVOS 1 El usuario introduce una opción no ofrecida por el sistema. 2 El usuario introduce datos no validos para la ejecución de su petición. 3

PRECONDICIONES 1 Ejecutar el módulo Client. 2 Exista un usuario interesado en hacer uso del sistema.

POSCONDICIONES 1 Desplegar los datos obtenidos como resultado de la ejecución de una aplicación a

través del sistema. 2 Indicarle al sistema cual va a ser la siguiente acción a ejecutar.

Caso de uso Server

CU2.- SERVER

PROYECTO:

Sistema balanceador de carga FECHA: 18 / Septiembre / 2004

AUTOR: Javier Pérez Barilla CLAVE: CU2 NIVEL ALCANCE Resumen muy general Organización (caja negra) Resumen x Organización (caja blanca) Actividad de usuario Módulo X Detalle Método

DESCRIPCIÓN BREVE Mediante el módulo Server se atienden todas aquellas peticiones que le llegan al nodo que funge como nodo Servidor.

ACTORES

Reporte de proyecto terminal 43

Actor principal Administrador del sistema. Actores secundarios

EVENTOS QUE LO INICIAN 1 Ejecutar la clase Server. 2 El usuario realice peticiones al sistema, y estos se realicen remotamente.

FLUJO DE EVENTOS PRIMARIO 1 Ejecutar el módulo Server. 2 El sistema crea el canal de comunicación a través del cual se le podrán hacer

peticiones. 3 El sistema registra el canal antes creado para que se puedan llevar a cabo las

comunicaciones remotas a través de éste. 4 El sistema está en espera de que le lleguen peticiones. 5 El sistema ejecuta la petición que le llego y devuelve los resultados al host que le

hizo la petición. 6 El sistema regresa al punto 4. 7 Fin. 8 9 10 11

FLUJO DE EVENTOS ALTERNATIVOS 1 Se rompe el canal de comunicación a través del cual se entablo la comunicación. 2 Llega una petición que no se encuentra definida dentro de la clase ServiceClass.

PRECONDICIONES 1 Ejecutar el módulo Server. 2 Crear un canal de comunicación a través del cual se podrán recibir las peticiones que

le lleguen.

POSCONDICIONES 1 Regresar los resultados de ejecutar el proceso que se pidió ejecutará. 2 Cerrar el canal de comunicación a través del cual se escuchaban las peticiones.

Reporte de proyecto terminal 44

3) Navegación de pantallas.

Es importante hacer mención que en realidad no se manejan diferentes pantallas, sino más bien son instancias de una misma pantalla pues le hacemos recordar que la aplicación de nuestro sistema se realizo implementando un entorno de línea de comandos y no un entorno grafico.

Navegación de Pantallas Client

Edo. Inicial

Menu de Aplicaciones

Introduce Datos

Ordena Datos

Indica Siguiente Accion a Ejecutar

Edo. Final

Selecciona Opcion Introducir Datos

Selecciona Ordenar Datos

Despues de Ejecutar el Proceso

Despues de Ejecutar el Proceso

El usuario determino salir de la aplicaión

El usuario determino seguir en la aplicación

Navegación de pantallas Server

Edo Inicial (despues de ejecutar Server.cs)

Pantalla Inicial (Espera Peticiones)

Atiende Peticiones

Edo. Final (se termina la ejecucion de la clase Server.cs)

Regresa resultados al Host que le hizo la peticion / [y vueve a esperar asta que le llega otra peticion]

llega una peticion

Reporte de proyecto terminal 45

Los resultados que obtuvimos de la fase de construcción del sistema son:

1) codificación del sistema. Toda la codificación del sistema se encuentra en el ANEXO A. 2) Diagrama de secuencia del sistema. Mediante el siguiente diagrama representamos la secuencia que sigue nuestro sistema para poder atender las peticiones que le hacen los usuarios.

Client mAsignador ServiceClass Server1.-El módulo Client se ejecuta

2.-El usuario hace una peticion al sistema

3.-El sistema Búsca el nodo con menos carga de trabajo

4.1.- Cuando el proceso fue asignado a un nodo diferente del local (cuando el proceso se ejecuta remotamente)

4.2.- Cuando el proceso fue asignado al Host Local (el proceso se ejecutará localmente)

Busca_Nodo_Menos_Cargado() Maquina_Local()getDate()

Regresa % de uso de CPU de máquina Local

Visita_Maquina1(Dir_IP)

getDate()

Regresa % de uso de CPU de máquina Remota

Regresa % de uso de CPU de máquina Remota

Visita_Maquina_k(Dir_IP)

getDate()

Regresa % de uso de CPU de máquina Remota

Regresa % de uso de CPU de máquina RemotaRegresa la Direccion IP de la Máquina con menos trabajo

RemoteConfigurationRegisterWellKnownCl ientType(RemoteType)

Introduce_Datos() u Ordena_Datos()

Regresa los Resultados

Regresa los Resultados

Introduce_Datos() u Ordena_Datos()

Regresa l os Resultados

Reporte de proyecto terminal 46

3) Inicialización del sistema. Para compilar y ejecutar el balanceador de carga escriba los siguientes comandos en un símbolo del sistema:

csc /t:library TrackingHandler.cs csc /r:System.Runtime.Remoting.dll /t:library /out:ServiceClass.dll

serviceclass.cs ésta última instruccion también la podemos escribir de la siguienta manera csc /t:library ServiceClass.cs

csc /t:library MiServiceClass.cs csc /t:library /r:ServiceClass.dll /r:MiServiceClass.dll mAsignador.cs csc /r:ServiceClass.dll /r:mAsignador.dll Client.cs csc /r:TrackingHandler.dll /r:ServiceClass.dll server.cs

Si el sistema lo quiere ejecutar en una sola terminal siga los siguientes pasos: En una pantalla de línea de comando ejecute el módulo client para echar a andar el sistema; abrir tantas pantallas de línea de comando como procesadores remotos quiera simular, en cada una de estas pantallas ejecute el modulo server. Obteniendo como resultado lo siguiente:

Reporte de proyecto terminal 47

Pero si el sistema lo ejecuta empleando más de una terminal entonces lo único que tiene que hacer es ejecutar en cada terminal los módulos client y server, cada uno en una pantalla de línea de comando. 4) Resultados obtenidos al ejecutar la aplicación. Los resultados que se deben obtener cuando la aplicación de nuestro sistema se lleva a cabo de forma exitosa son:

Cuando la aplicación ha sido ejecutada exitosamente los servidores están en condiciones de atender las peticiones que les lleguen, además el cliente tiene todas las condiciones necesarias para que el usuario pueda interactuar con el sistema. El sistema a través del módulo Cliente le solicita al usuario que seleccione el proceso que quiere ejecutar. Si el usuario selecciona la opción introducir datos, entonces el sistema despliega la siguiente pantalla:

Reporte de proyecto terminal 48

El sistema le pide al usuario que inserte el primero de los datos. El sistema no pasa de este punto hasta que el usuario introduzca el dato y presiones enter. Esta pantalla se repite hasta que el usuario ha introducido todos los datos que el sistema requiere para poder ejecutar el proceso solicitado por el usuario. Una vez que el usuario ha introducido todos los datos la siguiente pantalla que muestra el sistema es la siguiente:

Si el usuario presiona la opción de continuar en el sistema entonces el sistema despliega la pantalla inicial y entonces el proceso se repite.

Reporte de proyecto terminal 49

Pero si el usuario selecciona la opción de salir, entonces el sistema da por terminada la aplicación y muestra la siguiente pantalla:

Si el usuario selecciono la opción de ordenar datos entonces el sistema muestra la siguiente pantalla:

Reporte de proyecto terminal 50

Una vez que el sistema ha realizado el proceso de ordenar los datos entonces pide al usuario que indique si quiere continuar en la aplicación del sistema o si desea terminar la aplicación. Si el usuario selecciona la opción de continuar en el sistema entonces despliega la pantalla inicial.

Reporte de proyecto terminal 51

Pero si el usuario selecciono la opción de salir de la aplicación, entonces el sistema muestra la siguiente pantalla:

Cuando la aplicación no fue ejecutada correctamente se obtiene alguno de los siguientes errores:

Uno de los errores más importantes es el siguiente:

Este error se da cuando se intenta conectar con un servidor empleando una clase que ya ha sido ocupada anteriormente. Es decir se intenta conectar por n-esima vez con un servidor empleando una clase que ya se encuentra en uso. Otro de los errores que obtuvimos como resultado fue el siguiente:

Reporte de proyecto terminal 52

Este error se da cuando se intenta compilar un archivo que no se encuentra en el directorio en el que nos encontramos ubicados actualmente. El siguiente error se da cuando se intenta compilar un archivo que requiere de alguna librería en especial, y ésta no se indica específicamente. En este caso la librería que se requiere es /r:ServiceClass.dll

Reporte de proyecto terminal 53

Al especificarle la librería que le hace falta obtenemos como resultado lo siguiente:

Como puede observar la compilación del archivo se llevo a cabo exitosamente, ya que se le ha indicado explícitamente la librería o librerías que deberá implementar. Esta pantalla la obtenemos cuando se termina la aplicación de alguno de los servidores.

Otro de los resultados erróneos que obtuvimos en la aplicación de nuestro sistema es el siguiente:

Reporte de proyecto terminal 54

Esta pantalla la obtenemos cuando el usuario ha seleccionado la opción de introducir datos y el sistema le solicita que inserte el dato y presione enter, paro entonces el usuario no introduce dato alguno y si presiona enter. Es entonces cuando el sistema detecta que se ha actuado de forma errónea.

Reporte de proyecto terminal 55

8. CONCLUSIONES.

Una vez que se termino de construir nuestro sistema se considera se obtuvieron resultados positivos ya que el propósito fundamental de nuestro trabajo de investigación se pudo llevar a cabo de forma exitosa. Al inicio de nuestro trabajo de investigación se considero como posible alternativa para poder llevar a cabo la codificación de nuestro sistema el empleo de la plataforma .NET en especial se hizo referencia al lenguaje de programación C#. Por lo que se tuvo que realizar previo a la implementación de ésta herramienta una amplia investigación de los alcances que se pudieran obtener de dicha herramienta. Obteniendo como resultado una amplia gama de aplicaciones distribuidas y paralelas, por lo que se decidió adecuar a las necesidades de nuestra propuesta las clases y funciones ya existentes de dicha plataforma que aunadas con las clases y funciones que propusimos se pudieron lograr los objetivos de nuestros Proyectos Terminales I y II En lo que se refiere a la parte de la tecnología a emplear en nuestro trabajo de investigación. A pesar de que nuestro sistema fue probado a través de un conjunto de Host simulados se considera que el rendimiento y funcionalidad del mismo fue el esperado, ya que cuando un usuario realizaba alguna petición al sistema éste funcionaba como si en realidad el sistema estuviera corriendo a través de un conjunto de computadoras, es decir el sistema realmente simulaba a un sistema paralelo. Otro de los alcances significativos que se pudieron obtener fue el siguiente: A pesar de que el propósito fundamental de nuestro trabajo de investigación consistía en averiguar los alcances que se podían obtener de la herramienta .NET sobre aplicaciones paralelas y distribuidas , además se pudo lograr que el sistema generado este casi listo para que pueda correr sobre un conjunto real de computadoras.(lo único que se tiene que realizar es cambiar las direcciones IP’s ficticias por las direcciones IP’s reales de las respectivas máquinas que intervengan en el sistema). Del punto anterior podemos concluir que nuestro trabajo de investigación podrá ser implementado como una base para trabajos futuros que tengan el mismo enfoque y que pretendan emplear la misma herramienta de trabajo.

Reporte de proyecto terminal 56

9. RECOMENDACIONES.

Uno de los trabajos a futuro que se visualiza es la creación de una aplicación distribuida o paralela para el mejor rendimiento de los laboratorios distribuidos de la Universidad Autónoma Metropolitana, adoptando como base nuestro trabajo, e implementando la tecnología .NET.

Reporte de proyecto terminal 57

10. BIBLIOGRAFÍA.

Tesis de maestría: Balance Dinámico de Carga en un Sistema Paralelo con Memoria Distribuida. Centro de investigación y de estudios avanzados del I.P.N. Miguel Alfonso Castro García. Titulo: El lenguaje de programación C# Autor: Fco. Javier ceballos. Editorial: Alfaomega. Manual de Uso de la Plataforma NET. Msdn training de Microsoft. www.dc.uba.ar/people/materias/so/datos/cap09.pdf www.hispafuentes.com/hf-doc/temas/herramientas/clustering/node10_ct.html labsopa.dis.ulpgc.es/scon/PRESENTACIONES/Arquitecturas%20paralelas.doc http://strix.ciens.ucv.ve/~matcomp/algpar/CLASE1.html http://asds.dacya.ucm.es/nacho/pp_archivos/Arquitecturas%20Paralelas.pdf direcciones para detalles de computacion en paralelo http://gias720.dis.ulpgc.es/Doctorado/B13b.html Computación en Paralelo bibliografia: [CARLINI91]. U. de Carlini and U. Villano. Transputers and parallel architectures. message-passing distributed systems. Ellis Horwood Series in Computers and their applications. England. [COK91]. R.S. Cok. Parallel programs for the transputer. Prentice Hall. Englewood Clifs, NJ. [COOK80]. S.A. Cook. Towards a complexity theory of synchronuos parallel computation. L'Enseignement Mathematique 30. ** [ELLISON91]. D. Ellison. Understanding occam and the transputer. Sigma Press. England. [FORTUNE78]. S. Fortune and J. Wyllie. Parallelism in random access machines. Proceedings of the 10th Annual ACM Symposium on Theory of Computing, pp. 114-118.

Reporte de proyecto terminal 58

ANEXO A Código de clase Server.cs //librerias empleadas en esta clase using System; using System.Runtime.Remoting; using System.Runtime.Remoting.Channels; using System.Runtime.Remoting.Channels.Tcp; using System.Runtime.Remoting.Services; //indica el nombre de la clase public class ServerProcess{ //punto de entrada y salida de nuestro programa Servidor public static void Main(string[] Args){ //TcpChannel abre y almacena en caché una conexión por cada subproceso que presente //solicitudes a otro servidor en ese momento. Las conexiones de los sockets se cierran //en el cliente si se tiene un periodo de inactividad de entre 15 y 20 segundos. TcpChannel channel = new TcpChannel(8080); //se registra el canal a través del cual se realizará la comunicación. ChannelServices.RegisterChannel(channel); Console.WriteLine("Máquina 8080"); //Registra un nuevo controlador de seguimiento con TrackingServices. //TrackingServices Proporciona un medio para registrar, anular el registro y obtener //una lista de controladores de seguimiento TrackingServices.RegisterTrackingHandler(new TrackingHandler()); ServiceClass service = new ServiceClass(); //Convierte el MarshalByRefObject especificado en una instancia de la clase ObjRef, que //puede serializarse para su transmisión entre dominios de aplicación y a través de una red. ObjRef obj = RemotingServices.Marshal(service,"TcpService"); Console.WriteLine("\r\nPress Enter to unmarshal the object."); Console.ReadLine();

Reporte de proyecto terminal 59

//Convierte ObjRef en cuestión en un objeto proxy. RemotingServices.Unmarshal(obj); //Anula el registro de un canal determinado de la lista de canales. //da por terminada la comunicación remota RemotingServices.Disconnect(service); } }

Reporte de proyecto terminal 60

Código de clase Server2.cs using System; using System.Runtime.Remoting; using System.Runtime.Remoting.Channels; using System.Runtime.Remoting.Channels.Tcp; using System.Runtime.Remoting.Services; public class ServerProcess { public static void Main(string[] Args) { //El TcpChannel abre y almacena en caché una conexión por cada subproceso que presente //solicitudes a otro servidor en ese momento. Las conexiones de los sockets se cierran //en el cliente después de entre 15 y 20 segundos de inactividad. TcpChannel channel = new TcpChannel(8081); ChannelServices.RegisterChannel(channel); Console.WriteLine("Máquina 8081"); TrackingServices.RegisterTrackingHandler(new TrackingHandler()); ServiceClass service = new ServiceClass(); //antes de usar una conexion con un objeto de esta clase se debera cerrar la conexion //por si acaso ya existierá una conexion anterior //RemotingServices.Disconnect(service); ObjRef obj = RemotingServices.Marshal(service,"TcpService"); Console.WriteLine("\r\nPress Enter to unmarshal the object."); Console.ReadLine(); RemotingServices.Unmarshal(obj); //Console.WriteLine("Press Enter to disconnect the object."); //Console.ReadLine(); RemotingServices.Disconnect(service); } }

Reporte de proyecto terminal 61

Código de clase Server3.cs using System; using System.Runtime.Remoting; using System.Runtime.Remoting.Channels; using System.Runtime.Remoting.Channels.Tcp; using System.Runtime.Remoting.Services; public class ServerProcess{ public static void Main(string[] Args){ //El TcpChannel abre y almacena en caché una conexión por cada subproceso que presente //solicitudes a otro servidor en ese momento. Las conexiones de los sockets se cierran //en el cliente después de entre 15 y 20 segundos de inactividad. TcpChannel channel = new TcpChannel(8082); ChannelServices.RegisterChannel(channel); Console.WriteLine("Máquina 8082"); TrackingServices.RegisterTrackingHandler(new TrackingHandler()); MiServiceClass service = new MiServiceClass(); //antes de usar una conexion con un objeto de esta clase se debera cerrar la conexion //por si acaso ya existierá una conexion anterior //RemotingServices.Disconnect(service); ObjRef obj = RemotingServices.Marshal(service,"TcpService"); Console.WriteLine("\r\nPress Enter to unmarshal the object."); Console.ReadLine(); RemotingServices.Unmarshal(obj); //Console.WriteLine("Press Enter to disconnect the object."); //Console.ReadLine(); RemotingServices.Disconnect(service); } }

Reporte de proyecto terminal 62

Código de clase Client.cs //Librerias empleadas en la clase Client using System; using System.Diagnostics; using System.Reflection; using System.Runtime.Remoting; using System.Runtime.Remoting.Channels; using System.Runtime.Remoting.Channels.Tcp; //indica el nombre del constructor public class ClientProcess { //constructor por default de la clase public ClientProcess(){ } //punto de entrada y salida de la clase Client public static void Main(string[] Args){ ServiceClass services = new ServiceClass(); mAsignador Mod_Asign = new mAsignador(); string Cad, Dir1 = "tcp://localhost:" ,Dir2 = "/TcpService", Id_Cpu; int Opc, Id_Procesador; bool Connect1 = false, Connect2 = false; //él programa se ejecuta mientras el usuario así lo quiera do { //como se puede notar service es local a este ciclo ServiceClass service = new ServiceClass(); Console.WriteLine("Seleccione Una Opcion\n1.-Introducir Datos.\n2.-Ordenar Datos."); Cad = Console.ReadLine(); Opc = Int32.Parse(Cad); if(Opc != 1 && Opc != 2) Opc = 2; //Con esta parte del código se forma la direccion del canal a traves del cual //ejecutaremos el proceso remotamente. Id_Procesador = Mod_Asign.Busca_Nodo_Menos_Cargado(/*Connect1, Connect2*/);

Reporte de proyecto terminal 63

Id_Cpu = System.String.Concat(Dir1, Id_Procesador); Id_Cpu = System.String.Concat(Id_Cpu, Dir2); //dependiendo del procesador que se haya detectado como el más ocioso será el //tipo de ejecución que se realice. (local o remotamente) switch(Id_Procesador) { //ejecutando proceso localmente case 8080: Console.WriteLine("Máquina Local: Ejecutando Proceso Localmente..."); if(Opc == 1) { services.IntroduceDatos(); } else if(Opc == 2) { services.OrdenaDatos(); } break; //ejecutando proceso remotamente case 8081: Console.WriteLine("Máquina Remota {0}: Ejecutando Proceso Remotamente...", Id_Procesador); //si se va a entablar la comunicación por primera vez, entonces se enlaza //el cliente con el servidor a través del canal adecuado. de lo //contrario el cliente únicamente realiza su petición al servidor. if(Connect1 == true/*false*/) { ChannelServices.RegisterChannel(new TcpChannel()); WellKnownClientTypeEntry remotetype1 = new WellKnownClientTypeEntry(typeof(ServiceClass),Id_Cpu/*"tcp://localhost:8080/TcpService"*/); RemotingConfiguration.RegisterWellKnownClientType(remotetype1); Connect1 = true;

Reporte de proyecto terminal 64

} if(Opc == 1) { services.IntroduceDatos(); } else if(Opc == 2) { services.OrdenaDatos(); } break; //ejecutando proceso remotamente case 8082: Console.WriteLine("Máquina Remota {0}: Ejecutando Proceso Remotamente...", Id_Procesador); //si se va a entablar la comunicación por primera vez, entonces se enlaza //el cliente con el servidor a través del canal adecuado. de lo //contrario el cliente únicamente realiza su petición al servidor. if(Connect2 == true/*false*/) { ChannelServices.RegisterChannel(new TcpChannel()); WellKnownClientTypeEntry remotetype2 = new WellKnownClientTypeEntry(typeof(ServiceClass),Id_Cpu/*"tcp://localhost:8080/TcpService"*/); RemotingConfiguration.RegisterWellKnownClientType(remotetype2); Connect2 = true; } if(Opc == 1) { services.IntroduceDatos(); } else if(Opc == 2) { services.OrdenaDatos(); } break;

Reporte de proyecto terminal 65

} Console.WriteLine("presione.\n1.-Para Continuar.\n2.-Para Salir."); Cad = Console.ReadLine(); Opc = Int32.Parse(Cad); if(Opc != 1 && Opc != 2) Opc = 1; }while(Opc == 1); } }

Reporte de proyecto terminal 66

Código de clase TrackingHandler.cs //librerias empleadas en esta clase using System; using System.Runtime.Remoting; using System.Runtime.Remoting.Channels; using System.Runtime.Remoting.Services; //indica el nombre de la clase. pero además en este caso la sintaxis TrackingHandler : ITrackingHandler //indica que TrackingHandler es una subclase de la clase ITrackingHandler, por lo que la //clase TrackingHandler hereda todas las propiedades de la clase ITrackingHandler public class TrackingHandler : ITrackingHandler{ //el procedimeinto MarshaledObject es una funcion de la clase ITrackingHandler (ITrackingHandler.MarshaledObject()). //Notifica a la instancia actual que ya se han calculado las referencias de un objeto.(Notifies a handler that an object has been marshaled.) public void MarshaledObject(Object obj, ObjRef or) { Console.WriteLine("Tracking: An instance of {0} was marshaled. The instance HashCode is: {1}", obj.ToString(), obj.GetHashCode().ToString()); Console.WriteLine("ObjRef dump:"); if (or.ChannelInfo != null){ Console.WriteLine(" -- ChannelInfo: "); DumpChannelInfo(or.ChannelInfo); } if (or.EnvoyInfo != null) Console.WriteLine(" -- EnvoyInfo: " + or.EnvoyInfo.ToString()); if (or.TypeInfo != null){ Console.WriteLine(" -- TypeInfo: " + or.TypeInfo.ToString()); Console.WriteLine(" -- " + or.TypeInfo.TypeName); } if (or.URI != null) Console.WriteLine(" -- URI: " + or.URI.ToString()); } //averiguar la traducción de esta función (creo que despliega las propiedades del canal //a traves del cual se transmitira la comunicación)

Reporte de proyecto terminal 67

private void DumpChannelInfo(IChannelInfo info){ foreach(object obj in info.ChannelData){ if(obj is ChannelDataStore){ foreach(string uri in ((ChannelDataStore)obj).ChannelUris) Console.WriteLine(" -- ChannelUris:" + uri); } } } //el procedimeinto UnmarshaledObject() es una función de la clase ITrackingHandler((ITrackingHandler.UnmarshaledObject()) //Notifica a la instancia actual que ya se han resuelto las referencias de un objeto. public void UnmarshaledObject(Object obj, ObjRef or) { Console.WriteLine("Tracking: An instance of {0} was unmarshaled. The instance HashCode is: {1}", obj.ToString(), obj.GetHashCode().ToString()); } //el procedimeinto DisconnectedObject() es una función de la clase ITrackingHandler(ITrackingHandler.DisconnectedObject()) //Notifica a la instancia actual que se ha desconectado un objeto de su proxy public void DisconnectedObject(Object obj){ Console.WriteLine("Tracking: An instance of {0} was disconnected. The instance HashCode is: -->{1}", obj.ToString(), obj.GetHashCode().ToString()); } }

Reporte de proyecto terminal 68

Código de clase ServiceClass.cs //librerias en uso en esta clase using System; using System.Diagnostics; using System.Runtime.Remoting; using System.Runtime.Remoting.Channels; //indica el nombre de la calse. además en este caso la sintaxis ServiceClass : MarshalByRefObject //indica que ServiceClass es una subclase de la clase MarshalByRefObject, por lo que la clase //ServiceClass hereda todas las propiedades de la clase MarshalByRefObject public class ServiceClass : MarshalByRefObject{ //definicion de atributos de la clase. private DateTime starttime; private int Dato; private int[] Array = new int[3]; //constructor de la clase public ServiceClass(){ Console.WriteLine("A ServiceClass has been created."); //Dato = 18; starttime = DateTime.Now; } //destructor de la clase ~ServiceClass(){ Console.WriteLine("ServiceClass being collected after " + (new TimeSpan(DateTime.Now.Ticks - starttime.Ticks)).ToString() + " seconds."); } //funcion con la que se obtiene la fecha y hora del sistema public DateTime GetServerTime(){ Console.WriteLine("Time requested by client o client3."); return DateTime.Now; } //función con la que se obtiene(simula)el % de uso del procesador de una determinada máquina public int getDate(){ Random rnd = new Random();

Reporte de proyecto terminal 69

//Console.WriteLine("Time requested by client2."); Dato = rnd.Next(1, 50); return (Dato); } //función con la que se pide al usuario que introduzca datos public void IntroduceDatos(){ string Cad; int i = 0; Console.WriteLine("Introduzca Los Datos..."); for(i=0;i<3;i++){ Console.WriteLine("Introduzca El Dato[{0}]:", i); Cad = Console.ReadLine(); Array[i] = Int32.Parse(Cad); } Console.WriteLine("Los Datos Introducidos Son:"); for(i=0;i<3;i++) Console.WriteLine("Dato[{0}]={1} ", i, Array[i]); } //función con la que se ordenan los datos introducidos(si los hay). en este caso //se emplea el método de la burbuja para realizar el ordenamiento de los datos public void OrdenaDatos(){ int i = 0, j = 0, Aux = 0; Console.WriteLine("Los Datos Originales Son:"); for(i=0;i<3;i++) Console.WriteLine("Dato[{0}]={1}", i, Array[i]); for(i=0;i<3;i++){ for(j=0;j<3;j++){ if(Array[i]<Array[j]){ Aux = Array[j]; Array[j] = Array[i]; Array[i] = Aux; } } } Console.WriteLine("Los Datos Ordenados Son:"); for(i=0;i<3;i++) Console.WriteLine("Dato[{0}]={1}", i, Array[i]); } }

Reporte de proyecto terminal 70

Código de clase mAsignador.cs //Clase que se emplea para determinar en que nodo(Procesador) se deberá ejecutar //un determinado Proceso //librerias empleadas en esta clase using System; using System.Diagnostics; using System.Reflection; using System.Runtime.Remoting; using System.Runtime.Remoting.Channels; using System.Runtime.Remoting.Channels.Tcp; //indica el nombre de la clase public class mAsignador { //Área de atributos de la clase private string Dir1, Dir2, Dir3; private bool Connect1; private bool Connect2; //Constructor de la clase public mAsignador(){ //método que permite asociar las direcciones de las máquinas que forman el cluster Inicializa_Direcciones(); } //función que permite identificar el nodo(procesador) más ocioso del cluster //esta función es el equivalente al "VECTOR DE CARGA DEL SISTEMA" regresa un //valor entero que indica el numero del procesador identificado como el más ocioso public int Busca_Nodo_Menos_Cargado(){ int Id_Cpu = 0, Cpu_En_Uso = 0, Aux = 0; Console.WriteLine("--------------------------------------"); Console.WriteLine("| Buscando Nodo Menos Cargado... |"); Console.WriteLine("--------------------------------------"); Console.WriteLine("mAsignador Dir1: " + Dir1);

Reporte de proyecto terminal 71

Cpu_En_Uso = Maquina_Local(); Id_Cpu = 8080; Console.WriteLine("-------------------------------------------------------"); Console.WriteLine("mAsignador Dir2: " + Dir2); Aux = Visita_Maquina1(Dir2); if(Cpu_En_Uso > Aux) { Cpu_En_Uso = Aux; Id_Cpu = 8081; } Console.WriteLine("-------------------------------------------------------"); Console.WriteLine("mAsignador Dir3: " + Dir3); Aux = Visita_Maquina2(Dir3); if(Cpu_En_Uso > Aux) { Cpu_En_Uso = Aux; Id_Cpu = 8082; } Console.WriteLine("-------------------------------------------------------"); return(Id_Cpu); } //con esta función se detecta el % de uso del procesador de la máquina local. esta //función se realiza localmente public int Maquina_Local(){ int Cpu_En_Uso = 0; ServiceClass service = new ServiceClass(); Cpu_En_Uso = service.getDate(); Console.WriteLine("CPU EN USO: " + Cpu_En_Uso); return(Cpu_En_Uso); } //función que detecta el % de uso del procesador de una de las máquinas del cluster. //dicha máquina no se trata de la máquina local. la consulta se realiza remotamente public int Visita_Maquina1(string Dir){ ServiceClass service = new ServiceClass(); int Cpu_En_Uso = 0; TcpChannel NewTcpChannel = new TcpChannel();

Reporte de proyecto terminal 72

ChannelServices.RegisterChannel(NewTcpChannel); //si no existe una conexión con el canal a través del cual nos comunicaremos,entonces //se entabla la comunicación de lo contrario simplemente se ejecuta la consulta remota if(Connect1 == false) { //entabla conexion remota con la máquina 1 del cluster y le pide la informacion correspondiente WellKnownClientTypeEntry remotetype1 = new WellKnownClientTypeEntry(typeof(ServiceClass), Dir); RemotingConfiguration.RegisterWellKnownClientType(remotetype1); Connect1 = true; } Cpu_En_Uso = service.getDate(); Console.WriteLine("CPU EN USO: " + Cpu_En_Uso); // Anula el registro de un canal determinado de la lista de canales registrados. ChannelServices.UnregisterChannel(NewTcpChannel); return(Cpu_En_Uso); } //función que detecta el % de uso del procesador de una de las máquinas del cluster. //dicha máquina no se trata de la máquina local. la consulta se realiza remotamente public int Visita_Maquina2(string Dir) { MiServiceClass service = new MiServiceClass(); int Cpu_En_Uso = 0; TcpChannel NewTcpChannel = new TcpChannel(); ChannelServices.RegisterChannel(NewTcpChannel); //si no existe una conexión con el canal a través del cual nos comunicaremos,entonces //se entabla la comunicación de lo contrario simplemente se ejecuta la consulta remota if(Connect2 == false) { //entabla conexion remota con la máquina 1 del cluster y le pide la informacion correspondiente WellKnownClientTypeEntry remotetype1 = new WellKnownClientTypeEntry(typeof(MiServiceClass), Dir);

Reporte de proyecto terminal 73

RemotingConfiguration.RegisterWellKnownClientType(remotetype1); Connect2 = true; } Cpu_En_Uso = service.getDate(); Console.WriteLine("CPU EN USO: " + Cpu_En_Uso); //Anula el registro de un canal determinado de la lista de canales registrados. ChannelServices.UnregisterChannel(NewTcpChannel); return(Cpu_En_Uso); } //como su nombre lo indica únicamente se realizan inicializaciones con esta función public void Inicializa_Direcciones() { Dir1 = "tcp://localhost:8080/TcpService"; Dir2 = "tcp://localhost:8081/TcpService"; Dir3 = "tcp://localhost:8082/TcpService"; Connect1 = false; Connect2 = false; } //con esta función se cambia el estado de las conexiones public void Actualiza_Conexiones(){ Connect1 = true; Connect2 = true; } }

Reporte de proyecto terminal 74