sistema de distribuci n de carga para cluster de ...148.206.53.84/tesiuami/uami11940.pdf · brinda...

42
SISTEMA DE DISTRIBUCIÓN DE CARGA PARA CLUSTER DE SERVIDORES Proyecto de Investigación I y II. CBI. Universidad Autónoma Metropolitana. Licenciatura en Computación. Asesora: Graciela Román Alonso. Trimestre: 04-O. Autor: Miguel Angel García Vidal.

Upload: donga

Post on 07-Oct-2018

214 views

Category:

Documents


0 download

TRANSCRIPT

SISTEMA DE DISTRIBUCIÓN DE

CARGA PARA CLUSTER DE

SERVIDORES

Proyecto de Investigación I y II.

CBI.

Universidad Autónoma Metropolitana.

Licenciatura en Computación.

Asesora: Graciela Román Alonso.

Trimestre: 04-O.

Autor: Miguel Angel García Vidal.

1

Agradecimientos.

A mí querida Madre y Abuela, por haberme ayudado a terminar mis estudios profesionales.

A mí amada Novia,

por todo el apoyo que me ha dado durante toda la carrera siempre creyendo que podía hacer las cosas mejor.

A mis maestros,

que me han enseñado tanto en estos años para prepararme hacia el futuro.

A la Universidad,

y sobre todo a los encargados de los laboratorios de Sistemas distribuidos,

Supercómputo y visualización en Paralelo y de Docencia,

donde pude realizar las pruebas de este proyecto.

2

ÍNDICE.

I. Introducción 3

II. Objetivos del Proyecto. 5

III. El lenguaje Java. 6

IV. Arquitectura Propuesta. 8

- El Servidor. 9

- El Servidor Principal. 11

- Cliente. 11

- Archivos de configuración. 12

- Clase Peticiones. 13

V. Pruebas y Resultados. 14

- Prueba 1. 14

- Prueba 2. 14

- Prueba 3. 15

VI. Conclusiones. 16

Bibliografía. 17

Anexos. 18

- Anexo A Server.java 18

- Anexo B ServidorA.java 20

- Anexo C Atención.java 23

- Anexo D Transferencia.java 25

- Anexo E ServerG.java 27

- Anexo F ServidorG.java 29

- Anexo G Cliente.java 31

- Anexo H Cliente2.java 34

- Anexo I Peticiones.java 37

- Anexo J Peticiones2.java 39

3

I. INTRODUCCIÓN: Las computadoras han mejorado la vida de muchas maneras, y con la aparición

del Internet, esto a dado lugar a que día a día miles de usuarios se comuniquen a través

del mundo para realizar múltiples actividades que van desde consulta de información en

páginas Web a manejo de enormes Bases de Datos de forma remota. Es por esto que ha

surgido el término de cliente/servidor.

El término cliente/servidor describe un sistema en el que una máquina cliente

solicita a una segunda máquina llamada servidor que ejecute una tarea específica. El

cliente suele ser una computadora personal común conectada a una LAN, y el servidor,

por lo general es una máquina anfitriona, como un servidor de archivos PC, un servidor

de archivos de UNIX o una macrocomputadora o computadora de rango medio.

El programa cliente cumple dos funciones distintas: por un lado gestiona la

comunicación con el servidor, solicita un servicio y recibe los datos enviados por aquél.

Por otro, maneja la interfaz con el usuario: presenta los datos en el formato adecuado y

brinda las herramientas y comandos necesarios para que el usuario pueda utilizar las

prestaciones del servidor de forma sencilla.

El programa servidor en cambio, básicamente sólo tiene que encargarse de

transmitir la información de forma eficiente. No tiene que atender al usuario. De esta

forma un mismo servidor puede atender a varios clientes al mismo tiempo. Algunas de

las principales LAN cliente/servidor con servidores especializados que pueden realizar

trabajos para clientes incluyen a Windows NT, NetWare de Novell, VINES de Banyan

y LAN Server de IBM entre otros. Todos estos sistemas operativos de red pueden

operar y procesar solicitudes de aplicaciones que se ejecutan en clientes, mediante el

procesamiento de las solicitudes mismas.

4

Figura 1.

El desarrollo actual de sistemas cliente servidor se basa en la idea de máquinas

muy poderosas que pueden atender a diversos clientes al mismo tiempo o dos servidores

que atiendan las llamadas por separado. Esto podrá ser bueno para un número de

clientes determinados pero a gran escala como lo es Internet el sistema se hará lento y

en algunas ocasiones negará el servicio o simplemente no hará caso de un nuevo cliente.

Es por esto que actualmente se esta investigando los beneficios que se

obtendrían al utilizar una arquitectura de Clusters, para de esta manera mejorar el

rendimiento. Pero ¿qué es un Cluster? y ¿qué es la distribución de carga?

Un cluster es un número de computadoras unidas por un canal de

comunicaciones o una red, que comparten la misma base de datos, archivos de

configuración, etc. Son utilizadas para hacer labores que requieren mucho poder de

procesamiento y tiempo, asignándoles a cada una de las máquinas diferente tarea, es por

eso que se requiere de una distribución de carga bien balanceada para evitar que unas

maquinas no hagan nada mientras otras están muy ocupadas. Para poder realizar bien

esta distribución de carga existen diversos algoritmos de balanceo, que dependiendo de

la demanda y configuración requerida para el Cluster, sirven mejor o peor.

Es por esto que en el presente proyecto se implementara un sistema de cliente-

servidor mediante un cluster junto con un sistema de distribución, y de esta forma poder

sentar las bases para futuras implementaciones de diversos algoritmos de balanceo de

carga, para una distribución optima.

5

II. OBJETIVO DEL PROYECTO

El objetivo de éste proyecto es presentar las ventajas de tener un cluster de

servidores con distribución de carga, por medio de un algoritmo de balance de carga.

Entre las ventajas que podemos mencionar se encuentran:

• Es un sistema mucho más económico, ya que no requiere de maquinas muy

poderosas y obviamente costosas para realizar las tareas; de hecho se puede

hacer con un número dado de computadoras personales.

• Es fácil de construir, solo se necesita crear una red, y los sistemas operativos

adecuados como pueden ser:

o Windows NT, 2000, XP, 2003 Server.

o Unix, FreeBSD, Linux, Novell.

• Es más rápido, confiable y escalable.

6

III. El lenguaje Java.

El lenguaje Java es un lenguaje de alto nivel que fue creado por la empresa Sun

Microsystems no para uso académico como Pascal, ni fue hecho por una sola persona

como C o C++ sino que fue concebido con motivos comerciales, ya que generó un

interés avasallador debido a su fácil compatibilidad con la WEB.

Los programas en Java consisten en piezas llamadas clases y métodos; de esta

forma se pueden programar los componentes que vayamos a utilizar para crear nuestro

programa, pero la mayoría de programas hechos en Java utilizan las clases y métodos ya

creados; a esto se le llama reutilización del código en la programación orientada a

objetos. De esta manera uno utiliza los componentes ya creados encontrados en

colecciones de clases que existen ya en bibliotecas. Es por esta versatilidad que se

escogió a Java para la realización de éste proyecto.

Por lo general, los sistemas Java constan de varias partes: un entorno, el

lenguaje, la interfaz del programa o API y diversas clases con sus métodos. Para

programar en Java como en cualquier lenguaje es necesario pasar por las fases de

edición, compilación, carga, verificación y ejecución.

Para editar el código se utiliza cualquier editor de texto y el archivo creado se

guarda con extensión .java, hay editores que ofrecen más cosas (ayuda de clases,

autocorrección, diferentes colores para las clases, etc.) como lo son eclipse y

javacreator.

Para compilar un archivo en java se emite el comando javac, el compilador

traduce el programa a código de bytes, que es el lenguaje que entiende el interprete de

Java. Si el archivo se compila correctamente creara un archivo con el mismo nombre

pero con extensión .class, si no, marcará las clases donde hubo errores.

Antes de ejecutar el programa, es necesario colocarlo en la memoria. Esto lo

hace el cargador de clases que toma el archivo o archivos .class y os transfiere a

memoria. Esto se hace con el comando java, con lo cual ya después antes de que el

intérprete ejecute el código de bytes son verificados para que sean validos y no violen

las restricciones de seguridad de Java. Por ultimo la computadora interpreta el código y

lo ejecuta.

7

Las clases que se utilizaron para la comunicación entre el cliente y el servidor,

que de hecho son dos fueron la clase Socket y la clase ServerSocket, estas dos clases se

utilizan para abrir puertos y poder enviar información por esos canales sin importarnos

el como se envía la información por la red, ni mucho menos, o sea, simplemente se le

dan los bites a mandar y del otro lado simplemente los recibe.

Otra clase muy importante que se utilizo fue la clase Threads con la cual se

crean hilos de ejecución, para poder hacer un poco más óptimo el servicio de nuestro

servidor al poder ir atendiendo a varios clientes al mismo tiempo por ejemplo.

Por ultimo otras de las clases importantes que se utilizaron fueron las clases

FileInputStream y BufferedReader que se utilizan para poder escribir y leer de los

archivos respectivamente.

La versión de Java utilizada para la realización de este proyecto fue la

j2sdk1.4.2_04, s, para mayor información sobre las versiones de Java y las clases

disponibles se puede consultar la ayuda en línea de Sun para Java o descargarla del sitio

de Internet que se encuentra en la Bibliografía.

8

IV. ARQUITECTURA PROPUESTA:

La propuesta es hacer un cluster de servidores que atenderán a varios

clientes. Éste cluster tendrá que contener a un servidor primario el cual

balanceará la carga de peticiones entre los demás servidores que componen al

mismo.

Cada uno de los servidores que componen el cluster deberá de atender

las peticiones de diversos clientes que el servidor principal les envía con

solicitud de archivos en una ruta dada por estos clientes que puede estar en

una base de datos, como se muestra en la Figura 2.

Base de Datos

Servidores

Servidor. Principal.

Internet O

Red Local

Figura 2.

Clientes

9

Para que el servidor haga esto de una manera eficiente, se utiliza una

cola de peticiones, la cual va almacenando el socket de donde llega la petición

de cada uno de los clientes.

Dicha cola es un hilo que solo se encarga de encolar estas solicitudes de

los clientes, para posteriormente ser sacadas y atendidas por el servidor.

El servidor en si va sacando de esta cola un número dado de peticiones

y se pone a atenderlas; esta atención la va haciendo en una forma simultánea

gracias a que crea un número determinado de procesos hijos en forma de hilos,

los cuales tienen la función de atender al cliente enviando la información, o en

este caso, el archivo solicitado.

El Servidor.

El Servidor normal se compone esencialmente de tres clases como se

muestra en la Figura 3 las cuales son:

• ServidorA.class

• Atención.class

• Transferencia.class

La primera clase contiene a las otras dos, las cuales son clases que

extienden a la clase Threads; la clase Atención es en si la cola de prioridad,

mientras que la clase Transferencia es la que hace la transferencia de archivos

como su nombre lo indica.

Atención.class

Transferencia.class

ServidorA.class

Figura 3. Server.class.

10

La clase Servidor tiene un arreglo de objetos “Transferencia”, que va

creando conforme va sacando de la cola “Atención” los sockets de los clientes.

Una vez que el hilo de transferencia ha finalizado, el servidor saca otra petición

de la cola y se lo asigna a este hilo ya desocupado. Esto lo viene haciendo en

un ciclo infinito; en caso de que no haya clientes en la cola el sistema se queda

esperando hasta que haya alguno que atender.

La clase Transferencia se crea con un socket; con este socket crea un

canal de comunicaciones entre el servidor y el cliente, una vez ya creado este

canal el cliente manda el nombre del archivo que solicita; con este dato el

objeto Transferencia abre el archivo y se lo va mandando al cliente byte por

byte hasta llegar al final de archivo, tras lo cual cierra el archivo y el socket.

La clase Atención se crea con un número (que será el tamaño de la cola)

y el socket del servidor para una comunicación con éste; cuando éste objeto se

inicializa simplemente se queda esperando a que los clientes lo contacten y los

va encolando. Además cuenta con otros métodos, los cuales el servidor utiliza

para poder hacer las operaciones de sacar de la cola. Por cierto si la cola en

dado momento se llena y recibe otro cliente simplemente el método push

regresa el socket de este ultimo cliente no encolado; esto podrá ser útil en un

futuro para redireccionar este cliente a otro servidor.

Por ultimo existe una cuarta clase que es la que contiene el método main

que es la clase Server.class, la cual crea un objeto de la clase ServidorA y lo

inicializa para posteriormente ponerlo a funcionar.

Arreglo de clase

Transferencia

Cola Servidor Figura 4. Esquema del Servidor

11

El Servidor Principal.

El Servidor principal o ServidorG es el encargado de balancear de cierta

manera la carga de las peticiones realizadas por los clientes a los servidores.

Esta clase es muy parecida a un servidor normal, la diferencia consiste en qué

no crea hilos de transferencia, de hecho utiliza la misma clase de Atención para

poder atender a los clientes, el ServidorG.class simplemente crea la cola de

Atención y va sacando de ella la petición del cliente para decirle que servidor

se le asignará para ser atendido. Esta asignación se hace mediante una cola

circular de los servidores de que consta el cluster. Por último se tiene la clase

ServerG con el método main para inicializar al Servidor principal.

Figura 5. Esquema del ServidorG.

Cliente.

Por otra parte el cliente es una clase que tiene varios constructores el

más completo necesita: un nombre del servidor o dirección IP, un número de

puerto, un string para el nombre del archivo solicitado y otro string para el

nombre que va a tener el archivo descargado. Esta clase primero envía el

archivo solicitado al servidor y crea un archivo nuevo con el nombre

proporcionado, donde guardará la información que reciba del servidor; la forma

de recibir los datos es en un ciclo infinito que en el momento de que ya no

pueda leer nada por el canal se saldrá de dicho ciclo y cerrara el archivo y el

socket de comunicaciones.

Archivos de Configuración.

ServidorG

Cola

12

Se utilizó unos archivos de configuración para poder lograr que los

servidores tuvieran mayor flexibilidad al poder escoger el puerto por el que

escuchan, así como el número de nodos y sus IP o Hostname. Los archivos de

configuración son:

- Para el Servidor normal.- Este archivo debe de ser un documento de

texto que contenga por línea puerto, numero de clientes a atender al

mismo tiempo y el tamaño de la cola.

Ejemplo:

5000

5

50

- Para el Servidor General.- Este archivo de configuración contiene por

línea lo siguiente: numero de servidores con que consta el cluster, el

puerto por donde escucha, el tamaño de la cola, el puerto por donde

escuchan los servidores normales y finalmente los IP o Hostname de los

servidores normales que deben de ser el mismo numero de los

indicados arriba.

Ejemplo:

5

6000

100

5000

Host1

Host2

148.206.50.63

148.206.50.65

Host5

Clase Peticiones.

13

Esta clase fue implementada para poder realizar pruebas con el servidor,

la cual utiliza otra clase de cliente especial. Estos clientes tienen las mimas

funcionalidades que los originales, pero con la diferencia que todos son hilo; de

esta forma crea una serie de hilos de clientes, pero para poder hacer esto,

como ya se había dicho antes los clientes necesitan inicializar sus valores.

Esto lo hace leyendo de un archivo de configuración las rutas de los archivos

que cada cliente va a solicitar al servidor y se las da a cada uno de los hilos

clientes para que se comuniquen con el servidor. Por lo que este archivo de

configuración debe ser de la siguiente forma:

< Número de clientes >

< Nombre del servidor o IP >

< Puerto por donde se envía >

< Nombre del archivo cómo se va a guardar en el cliente>

< Nombre del archivo que se solicita (ruta completa)>

< Nombre del archivo cómo se va a guardar en el cliente>

14

V. PRUEBAS Y RESULTADOS. Se hicieron 3 pruebas con diferente número de servidores y archivos de

diferentes tamaños. Estas pruebas se realizaron con el propósito de comparar

el esquema de un solo servidor contra un Cluster de servidores con el algoritmo

de balanceo que se utiliza en la clase ServidorG. Para poder realizar estas

pruebas se hizo uso de la clase Peticiones, primero en una máquina, después

desde diferentes máquinas, para que las peticiones se realizaran desde

diferente IP, para que de este modo se simulara la petición de muchos clientes

desde diferentes lugares. Prueba 1. Tamaño de archivos:

• 23K temp.doc • 398K test1.exe • 2M test2.tar.gz • 4M test3.tgz

Configuración del Servidor Maestro (cluster): Número de servidores 2 Proceso atendido a la vez por cada servidor 1 Tamaño de la cola 4 Número de clientes. 4 Tiempos:

• Real 9 min. 21.240 seg. • User 0 min. 34.430 seg. • Sys 5 min. 20.220 seg.

Configuración del Servidor: Proceso atendido a la vez 1 Tamaño de la cola 4 Número de clientes. 4 Tiempos:

• Real 11 min. 35.126 seg. • User 0 min. 34.160 seg. • Sys 5 min. 2.520 seg.

Prueba 2. Tamaño de archivos:

2M test1.tar.gz 398K test2.exe 2M test3.tar.gz 4M test4.tgz 2M test5.tar.gz 398K test6.exe 2M test7.tar.gz 4M test8.tgz

Configuración del Servidor Maestro (cluster): Número de Servidores. 2 Procesos atendidos por cada servidor. 2 Tamaño de la cola. 10 Número de clientes. 8 Tiempos:

• Real 14min. 22.221seg • User 1min. 12.760seg. • Sys 12min. 21.860seg

Configuración del Servidor: Proceso atendido a la vez 2 Tamaño de la cola 10 Número de clientes. 8 Tiempos:

15

• Real 17min. 13.999seg. • User 1min. 9.180seg. • Sys 11min. 11.670seg.

Prueba 3.

Tamaño de archivos:

• 1,3M test1.txt

• 1,3M test2.txt

• 720K test3.mp3

• 1,3M test4.txt

• 7,8M test5.run

• 7,8M test6.run

• 720K test7.mp3

• 720K test8.mp3

Configuración del Servidor Maestro (cluster)

Número de Servidores. 4 Procesos atendidos por cada servidor. 2

Tamaño de la cola. 10 Número de clientes. 8

Tiempos:

• Real 3min. 14.348seg.

• User 1min. 16.887seg.

• Sys 1min. 27.366seg.

Configuración del Servidor:

• Proceso atendido a la vez 2 • Tamaño de la cola 10 • Número de clientes. 8

Tiempos:

• Real 20min. 7.382seg.

• User 1min. 20.187seg.

• Sys 1min. 25.827seg.

RESULTADOS.

En general las pruebas fueron satisfactorias, ya que como se muestran en la Gráfica 1 se disminuyo el tiempo de respuesta y transmisión de datos conforme el cluster era aun más grande a comparación de cuando solo se tenía un solo servidor, donde como se puede ver los tiempos son altos

Numero de servidores

561.24 862.221

194.348

695.126 1033.9991207.382

00.5

11.5

22.5

33.5

44.5

0 200 400 600 800 1000 1200 1400

Tiempos

Nu

mer

o d

e se

rvid

ores

16

Grafica 1. CONCLUSIONES. Se propuso un sistema de cliente servidor que bajara los tiempos de transferencia de archivos utilizando un algoritmo de balanceo de carga, lo cual como las pruebas lo indican se logró exitosamente. No obstante, esto no quiere decir que se halla llegado a lo óptimo ya que se utilizó un algoritmo de balance de carga muy sencillo con una cola circular. Esto se puede mejorar en un futuro sirviéndose de que el Servidor Principal puede comunicarse con los nodos (los otros servidores) y de esta forma poder saber el estado de sus colas, y de esta manera poder asignar a un cierto cliente que llegue con alguna petición a el servidor más indicado. En conclusión yo diría que este proyecto sirve como un punto de partida para poder posteriormente hacer pruebas e implementar otros algoritmos de balanceo dinámico mucho más efectivos de una forma más fácil y con los cambios mínimos de este proyecto.

17

BIBLIOGRAFÍA.

- Como Programar en Java. Deitel y Deitel

Pearson Educación.

- JavaTM 2 Platform Std. Ed. v1.4.2 Manual.

- http://java.sun.com/docs

18

ANEXOS Anexo A. Server.java /** * @(#)Server.java * * JFC Sample application * * @author Miguel Angel García Vidal * @version 1.00 04/10/04 */ import java.io.BufferedReader; import java.io.FileReader; import java.io.FileNotFoundException; import java.io.IOException; public class Server { public static void main(String[] args) { /* Se crea al servidor con un numero de clientes definido, un puerto * y un tamaño de cola. */ int num_servers,cola,port; BufferedReader file; if(args.length == 0) { System.out.println("Iniciando"); port = 50000; num_servers = 2; cola = 5; servidorA s = new servidorA(num_servers,port,cola); System.out.println("s.inicia"); s.inicia(); } else

19

{ if(args.length == 0) { System.out.println("Error, se debe proporcionar el archivo de configuración"); System.exit(1); } else { try { file = new BufferedReader(new FileReader( args[0]) ); port = new Integer(file.readLine() ).intValue(); num_servers = new Integer(file.readLine() ).intValue(); cola = new Integer(file.readLine() ).intValue(); servidorA s = new servidorA(num_servers,port,cola); s.inicia(); } catch(FileNotFoundException fnf) { System.out.println("No se encontró el Archivo de configuracion."); } catch(IOException ioe) { System.out.println("Error de E/S"); } } } } }

20

Anexo B. ServidorA.java /** * @(#)ServidorA.java * * JFC Sample application * * @author Miguel Angel García Vidal * @version 1.00 04/10/04 */ import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; class servidorA { private ServerSocket s; private Transferencia T[]; private Atencion A; private int max_ctes,port; private boolean busy; /* * @ServidorA * * max_ctes: es el máximo de clientes. * port: es el puerto por el cual va a escuchar. * tam: es el tamaño de la cola a crear. * * */ servidorA(int max_ctes,int port,int tam) { this.max_ctes = max_ctes; this.port = port; try { s = new ServerSocket(port); T = new Transferencia[max_ctes]; for(int i = 0; i< T.length;i++) { T[i] = null; } A = new Atencion(tam,s); busy = false; } catch(IOException e)

21

{ System.out.println("Error en servidorA al crearlo"); } } /* * @inicia * * Este método iniciliza el hilo de Atención y se * prepara a recibir a todos los clientes utilizando para ello * hilos de transferencia. * */ public void inicia() { int i = 0; Socket so; boolean atendido; A.start(); System.out.println("Después de A.start"); System.out.println("Valor de i es: "+i); System.out.println("Valor de max_ctes es: "+max_ctes); /*******************************************************/ while(true) { try { System.out.println("Entrando a los hilos"); if(A.i > 0) { so = A.pop(); if(so != null) { System.out.println("Creando hilo Transferencia"); atendido = false; while(!atendido) { if(T[i] == null) { T[i] = new Transferencia(so); T[i].start();

22

atendido = true; } else { if(T[i].busy == false) { T[i] = new Transferencia(so); T[i].start(); atendido = true; } } i = (i+1) % max_ctes; } } else { System.out.println("no hay pop"); } } else while(A.i == 0 ); System.out.println("Hay cliente"); } catch(Exception e) { System.out.println("Error al crear el hilo de transferencia"); } } /****************************************************/ } }

23

Anexo C. Atención.java /** * @(#)Atencion.java * * JFC Sample application * * @author Miguel Angel García Vidal * @version 1.00 04/10/04 */ import java.net.Socket; import java.net.ServerSocket; import java.io.IOException; class Atencion extends Thread { private Socket A[]; public int i; private ServerSocket serv; Atencion(int max,ServerSocket s) { System.out.println("Creando A de "+max); A = new Socket[max]; i=0; serv = s; } /* * Saca el primer elemento de la cola y recorre todos lo demas * regresa el socket y si esta vacía la cola null * */ public Socket pop() { Socket s; int j; if(i > 0) { s = A[0]; for(j=0;j<i-1;j++) A[j] = A[j+1]; i--; A[i] = null; return s;

24

} else return null; } /* * Encola las peticiones hechas al servidor * si se llega al limite de la cola se regresa el socket * ultimo recibido */ private Socket push(Socket s) { System.out.println("Encolando"); if(i<A.length) { A[i] = s; i++; return null; } else return s; } public void run() { Socket e = null; while(true) { try { System.out.println("Aceptando cliente"); e = push( serv.accept() ); } catch(IOException ioe) { System.out.println("Error en el hilo de Atención al encolar"); } } } }

25

Anexo D. Transferencia.java /** * @(#)Transferencia.java * * JFC Sample application * * @author Miguel Angel García Vidal * @version 1.00 04/10/04 */ import java.io.IOException; import java.io.DataOutputStream; import java.io.DataInputStream; import java.net.ServerSocket; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.net.Socket; public class Transferencia extends Thread { public String path; public Socket connection; public DataOutputStream out; public DataInputStream in; public boolean busy; /** * Method Transferencia * * * @param s * */ Transferencia(Socket s) { connection = s; try { /* Creando los canales de comunicación */ out = new DataOutputStream(connection.getOutputStream() ); in = new DataInputStream(connection.getInputStream() ); /* Recibiendo el nombre del archivo a enviar */ path = in.readUTF(); busy = false; }

26

catch(IOException e) { System.out.println("Error al obtener el OutputStream"); e.printStackTrace(); System.exit(1); } } /** * Method run * * */ public void run() { FileInputStream file; int b; try { file = new FileInputStream(path); busy = true; b = file.read(); while( b != -1) { out.writeByte(b); b = file.read(); } System.out.println("Cerrando el archivo y el socket"); file.close(); connection.close(); busy = false; } catch(FileNotFoundException e) { System.out.println("ERROR: No se encuentra el archivo"); System.exit(1); } catch(IOException e) { System.out.println("ERROR: b no se pudo crear"); System.out.println("ERROR: No se puede cerrar el Socket o el archivo"); System.exit(2); } }

27

}

Anexo E. ServerG.java /** * @(#)ServerG.java * * JFC Sample application * * @author Miguel Angel García Vidal * @version 1.00 04/10/04 */ import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; public class ServerG { public static void main(String[] args) { int myport,num_servers,i,tam,Uport; String servers[]; BufferedReader file; ServidorG S; /* Se crea al servidor con un numero de clientes definido, un puerto * y un tamaño de cola. */ try { if( args.length > 0 ) { file = new BufferedReader(new FileReader( args[0]) ); num_servers = (new Integer(file.readLine())).intValue(); System.out.println(num_servers); servers = new String[num_servers]; myport = new Integer(file.readLine() ).intValue(); System.out.println(myport); tam = new Integer(file.readLine() ).intValue(); System.out.println(tam); Uport = new Integer(file.readLine() ).intValue(); System.out.println(Uport);

28

for(i = 0; i< num_servers;i++) { servers[i] = file.readLine(); } S = new ServidorG(myport,tam,servers,Uport ); S.inicia(); } else { System.out.println("Forma de uso:"); System.out.println("ServerG <puerto> <numero de servidores> <tamaño de la cola> <archivo>"); } } catch(IOException e) { System.out.println("Error al inicializar servidorG"); } } }

29

Anexo F. ServidorG.java /** * @(#)ServidorG.java * * JFC Sample application * * @author Miguel Angel García Vidal * @version 1.00 04/10/04 */ import java.io.IOException; import java.io.DataOutputStream; import java.net.ServerSocket; import java.net.Socket; public class ServidorG { private ServerSocket s; private Atencion a; private String servers[]; private int Uport; ServidorG(int port, int size_a,String[] servers,int Xport ) { try { System.out.println("Socketserver"); s = new ServerSocket(port); System.out.println("Atención"); a = new Atencion(size_a,s); System.out.println(servers); this.servers = servers; System.out.println(Xport); Uport = Xport; a.start(); } catch(IOException e) { System.out.println("Error al inicializar el servidorG"); } } public void inicia() { Socket so; DataOutputStream out; int max = servers.length;

30

int i = 0; try { while(true) { so = a.pop(); if(so != null) { out = new DataOutputStream(so.getOutputStream() ); out.writeUTF(servers[i]); out.writeInt(Uport); out.close(); i = (i + 1) % max; } } } catch(IOException e) { System.out.println("Error con el socket"); } } }

31

Anexo G. Cliente.java /** * @(#)Cliente.java * * JFC Sample application * * @author Miguel Angel García Vidal * @version 1.00 04/10/04 */ import java.net.Socket; import java.io.IOException; import java.io.FileOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.EOFException; public class Cliente extends Thread { private Socket cliente; private int port; private String host_server; private FileOutputStream file; String s,o; /** * Method Cliente * * */ public Cliente(String s,String o) { host_server = "localhost"; port = 50000; this.s = s; this.o = o; } /** * Method Cliente * * */ public Cliente(int port,String server,String s, String o) { host_server = server;

32

this.port = port; this.s = s; this.o = o; } /** * Method inicia * * s: Archivo donde se va a guardar el archivo solicitado. * * o: Archivo solicitado. * */ private void inicia() { DataInputStream datos; DataOutputStream msg; int c; byte b; try { cliente = new Socket(host_server,port); datos = new DataInputStream(cliente.getInputStream()); /****************************************************/ /***** Cambio para el servidor general *****/ host_server = datos.readUTF(); port = datos.readInt(); System.out.println(host_server); cliente.close(); cliente = new Socket(host_server,port); datos = new DataInputStream(cliente.getInputStream()); msg = new DataOutputStream(cliente.getOutputStream()); /*****************************************************/ msg.writeUTF(o); file = new FileOutputStream(s); System.out.println("Entrando al ciclo de lectura"); while(true) { b = datos.readByte(); file.write(b); } }

33

catch(EOFException eof) { System.out.println("Se llego al final del archivo"); } catch(IOException ioe) { ioe.printStackTrace(); System.exit(1); } try { System.out.println("Cerrando el cliente"); cliente.close();//Se cierra el puerto del cliente file.close(); } catch(IOException ioe) { ioe.printStackTrace(); System.exit(1); } } public void run() { inicia(); } }

34

Anexo H. Cliente2.java /** * @(#)Cliente2.java * * JFC Sample application * * @author Miguel Angel García Vidal * @version 1.00 04/10/04 */ import java.net.Socket; import java.io.IOException; import java.io.FileOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.EOFException; import java.io.IOException; public class Cliente2 extends Thread { private Socket cliente; private int port; private String host_server; private FileOutputStream file; String s,o; /** * Method Cliente * * */ public Cliente2(String s,String o) { host_server = "localhost"; port = 50000; this.s = s; this.o = o; } /** * Method Cliente * * */ public Cliente2(int port,String server,String s, String o) {

35

host_server = server; this.port = port; this.s = s; this.o = o; } /** * Method inicia * * s: Archivo donde se va a guardar el archivo solicitado. * * o: Archivo solicitado. * */ private void inicia() { DataInputStream datos; DataOutputStream msg; int c; byte b; try { cliente = new Socket(host_server,port); datos = new DataInputStream(cliente.getInputStream()); msg = new DataOutputStream(cliente.getOutputStream()); /*****************************************************/ msg.writeUTF(o); file = new FileOutputStream(s); System.out.println("Entrando al ciclo de lectura"); while(true) { b = datos.readByte(); file.write(b); } } catch(EOFException eof) { System.out.println("Se llego al final del archivo"); } catch(IOException ioe) { ioe.printStackTrace();

36

System.exit(1); } try { System.out.println("Cerrando el cliente"); cliente.close();//Se cierra el puerto del cliente file.close(); } catch(IOException ioe) { ioe.printStackTrace(); System.exit(1); } } public void run() { inicia(); } }

37

Anexo I. Peticiones.java /** * @(#)Peticiones.java * * JFC Sample application * * @author Miguel Angel García Vidal * @version 1.00 04/10/04 */ import java.io.BufferedReader; import java.io.FileReader; import java.io.FileNotFoundException; import java.io.IOException; class Peticiones { public static void main(String args[]) { String solicitado="",guardar="",server = ""; Cliente cte[]; BufferedReader file; int i,num_cte,port; if(args.length != 0) { try { /* *Se pretende abrir el archivo de configuración para inicializar *a los clientes con las especificaciones del archivo. *El archivo debe constar de: * * numero de clientes * el nombre o IP del servidor. * el puerto por donde debe comunicarse. * Una secuencia de rutas de los archivos donde se

38

* va a guardar el archivo y abajo * donde esta el archivo en el servidor */ /*Archivo de configuración.*/ file = new BufferedReader(new FileReader( args[0]) ); num_cte = (new Integer(file.readLine())).intValue();//numero de clientes server = file.readLine();//hostname del servidor principal port = (new Integer(file.readLine() )).intValue();//puerto del servidro principal cte = new Cliente[num_cte];//Arreglo de clientes. for(i = 0;i < cte.length;i++) { guardar = file.readLine(); System.out.println(guardar); solicitado = file.readLine(); System.out.println(solicitado); cte[i] = new Cliente(port,server,guardar,solicitado); cte[i].start(); } file.close(); } catch(FileNotFoundException e) { System.out.println("Error no hay archivo"); } catch(IOException e) { System.out.println("Error de E/S"); } } else { System.out.println("Error no hay parámetros"); } } }

39

Anexo J. Peticiones2.java /** * @(#)Peticiones2.java * * JFC Sample application * * @author Miguel Angel García Vidal * @version 1.00 04/10/04 */ import java.io.BufferedReader; import java.io.FileReader; import java.io.FileNotFoundException; import java.io.IOException; class Peticiones2 { public static void main(String args[]) { String solicitado="",guardar="",server = ""; Cliente2 cte[]; BufferedReader file; int i,num_cte,port; if(args.length != 0) { try { /* *Se pretende abrir el archivo de configuración para inicializar *a los clientes con las especificaciones del archivo. *El archivo debe constar de: * * numero de clientes * el nombre o IP del servidor. * el puerto por donde debe comunicarse. * Una secuencia de rutas de los archivos donde se * va a guardar el archivo y abajo

40

* donde esta el archivo en el servidor */ /*Archivo de configuración.*/ file = new BufferedReader(new FileReader( args[0]) ); num_cte = (new Integer(file.readLine())).intValue();//numero de clientes server = file.readLine();//hostname del servidor principal port = (new Integer(file.readLine() )).intValue();//puerto del servidro principal cte = new Cliente2[num_cte];//Arreglo de clientes. for(i = 0;i < cte.length;i++) { guardar = file.readLine(); System.out.println(guardar); solicitado = file.readLine(); System.out.println(solicitado); cte[i] = new Cliente2(port,server,guardar,solicitado); cte[i].start(); } file.close(); } catch(FileNotFoundException e) { System.out.println("Error no hay archivo"); } catch(IOException e) { System.out.println("Error de E/S"); } } else { System.out.println("Error no hay parámetros"); } } }