Title: Qu
 1Qué pasa cuando varios clientes tratan de 
conectarse al mismo teimpo a un servidor 
- Una forma es ir atendiéndolos de a uno en un 
ciclo como en el programa que atiende pedidos de 
archivos  - Se acepta una conexión 
 - se lee la petición 
 - se lee desde el 
 - archivo y se escribe en el socket hasta encontrar 
una marca de fin de archivo  - A este tipo de servidores se les llama servidores 
iterativos  - El problema es que todo cliente tiene que esperar 
su turno para ser atendido  - Si uno de ellos pide un archivo muy grande los 
demás tienen que esperar  - La mayor parte de la espera es debido a 
operaciones de IO, hay capacidad de CPU ociosa !  
  2Un Servidor Concurrente 
- Un servidor concurrente atiende a varios clientes 
al mismo tiempo.  - Más aún, mientras está atendiendo sigue 
escuchando  - El problema es que todo cliente tiene que esperar 
su turno para ser atendido  - Si uno de ellos pide un archivo muy grande los 
demás tienen que esperar  - La mayor parte de la espera es debido a 
operaciones de IO, hay capacidad de CPU ociosa !  - Se trata de crear un nuevo proceso o línea de 
ejecución cada vez que un cliente llega a pedir 
un servicio.  
  3Algoritmo de Servidor Concurrente 
- Programa principal o master del servidor 
 - 1- Crear un Socket de servidor 
 -  En un ciclo infinito 
 -  2- aceptar requerimientos de clientes 
 -  3- cuando llega una petición de un cliente 
crear un nuevo  -  proceso esclavo que atienda 
paralelamente la petición  -  (esto no debe bloquear la ejecución del 
programa master  -  del servidor) 
 -  4 - volver a 2. 
 - Proceso esclavo 
 -  1- Recibir los parámetros de la comunicación 
(socket o flujos de entrada y/o salida)  -  2- Atender al cliente (ej leer el nombre del 
archivo, transmitir el archivo)  -  3- Retornar (desaparecer !) 
 
  4Cómo (y por qué) crear procesos paralelos 
- Si existe sólo una CPU, Por qué crear procesos 
paralelos?  - Porque algunos programas se escriben más 
fácilmente así. De hecho, la programación de un 
servidor es a veces más fácil si se hace de esta 
manera.  - Porque sí hay más de un procesador !!!!! 
(dónde?)  - El concepto de procesos paralelos implentados a 
nivel de S.O. aparecen con UNIX y C.  - La forma de crearlos es ejecutando una función 
llamada fork()  - int i  fork() provoca que se cree un proceso 
exactamente igual al que se está ejecutando.  - La única diferencia es que en el proceso hijo (el 
nuevo creado) la variable i vale cero. Esto se 
usa para saber quién soy yo.  - En programación de servidores concurrentes, si 
soy el hijo ejecuto la parte que corresponde al 
proceso esclavo.  - Si soy el padre (i tiene un valor distinto de 
cero y es el id del proceso hijo creado) sigo 
recibiendo peticiones  
  5Ejemplo de procesos paralelos en C (muy 
simplificado)
- main()  
 -  int pid, msock, ssock 
 -  sock  passivesock(port, tcp, qlen) 
 -  / ver capítulo 10.4 del libro Internetworking 
with tcp/ip de Douglas Commer para ver cómo se 
implementa /  -  while(1)  
 -  ssock  accept(msock, fsin, alen) 
 -  pid  fork() 
 -  if (pid  0)  
 -  atender al cliente 
 -  retornar 
 -   
 
  6Problemas con el fork() en UNIX
- La creación del proceso paralelo es costosa en 
tiempo.  - En algunos textos se sugiere que se podrían crear 
los procesos paralelos al levantar el servidor. 
Cuando llegue un cliente simplemente se le pasan 
los datos por medio de un pipe que se crea entre 
el proceso padre y el proceso hijo  - El proceso paralelo duplica exactamente todo el 
ambiente en el cual estaba corriendo el proceso 
original, incluso aquellas variables que no 
necesita !!!  - No es fácil manejar procesos paralelos, ya que si 
no se terminan en forma normal pueden quedar 
consumiendo recursos indefinidamente.  - La única información que tiene el padre para 
controlarlos es su identificación al crearlos.  - Muchas veces se prefiere usar el método select, 
que lo que hace es preguntar de una serie de 
puntos de lectura de datos (en este caso sockets) 
cuál está listo para ser leído este puede ser 
uno de los sockets de comunicación con cliente 
(en un arreglo) o el socket por donde se escuchan 
las peticiones (recordar que el IO es lo más 
lento en todo esto) 
  7En JAVA se prefiere usar Threads 
- Un thread es una secuencia o flujo de de 
instrucciones que se ejecutan dentro de un 
programa. Tiene un comienzo y un fin. Entonces 
qué diferencia tiene con un proceso ?  - El thread sólo puede ser creado dentro de un 
proceso. Y un proceso (programa) puede crear 
varios threads dentro de él que se ejecutan en 
paralelo.  - Entonces, qué diferencia tiene con el fork(). El 
programa principal está conciente de los 
threads que existen, hay variables que los 
identifican. Pueden ser creados, inicializados, 
sustendidos, reactivados o parados por el el 
programa que los creó.  - El programa principal puede darles parámetros 
distintos a cada thread. Los thread se pueden 
programar con la canatidad de variables 
necesarias para su ejecución (no lo heredan TODO)  
  8Usando threads para atender multiples clientes de 
un Servidor de Sockets
- La forma de implementar servidores que atiendan a 
varios clientes paralelamente a la vez es 
combinando threads con sockets  - El servidor abre un ServerSocket desde donde oye 
ciualquier intento por conectarse con él de un 
cliente.  - Una vez establecida la conexión, abre un socket 
normal e inicia un thread que atiende a este 
cliente. El socket abierto se pasa como 
parámetro. De esa manera puede seguir oyendo por 
el ServerSocket sin estar bloqueado.  - El thread tiene un método run que atiende los 
pedidos del cliente  - El cliente se conecta al servidor sin saber que 
finalmente será un socket el que está 
atendiéndolo. 
  9Implementación de Threads
- Una forma de usar Threads en Java es creando una 
nueva clase que extienda la clase Thread y 
sobreescribir el método run.  - Los threads son una clase existente. Esta clase 
se debe extender para hacer una clase derivada 
que haga lo que nosotros queramos.  - Lo que un thread en particular hace cuando se 
echa a correr se programa en un método llamado 
run de la clase extendida de Thread..  - El método run ejecuta cuando a un objeto de esta 
clase se le aplica el método start()  - El encabezado de una clase Thread será 
 - public class MiThread extends Thread  
 - Y en alguna parte deberá aparecer 
 - public void run()  
 - //aquí va lo que queremos que se haga en paralelo 
  
  10Ejemplo de Threads Como clase nueva
- public class SimpleThread extends Thread  
 -  public SimpleThread(String str)  
 -  super(str) 
 -   
 -  public void run()  
 -  for (int i  0 i lt 10 i)  
 -  System.out.println(i  " " 
 getName())  -  try  
 -  this.sleep((int)(Math.ra
ndom()  1000))  -   catch (InterruptedExceptio
n e)   -   
 -  System.out.println("DONE! "  
getName())  -   
 -   
 - El método this.sleep(milisegundos) debe ir en un 
bloque try and catch 
  11Ejemplo de Threads Uso de la clase nueva
- public class TwoThreadsTest  
 -  public static void main (String 
args)   -  SimpleThread t1,t2 
 -  t1  SimpleThread("Jamaica") 
 -  t2  SimpleThread("Fiji") 
 -  t1.start() t2.start() 
 -   
 -   
 - El método start() inicia la ejecucón de un 
thread. Esto implica que se empieza a ejecutar el 
código escrito en el método run del thread. 
También existen otros métodos que se le pueden 
aplicar a un thread suspend(), resume(), stop(). 
  12Qué pasa no se puede usar extends?
- Si el servidor también tiene una interfaz gráfica 
(extends Frame) o está en un applet (extends 
Applet) no puede a la vez extender el thread  - Se usa la implementación de la interfaz Runnable, 
lo que implica que la clase debe implementar el 
método run().  - Para iniciar una ejecución paralela del método 
run se debe crear un objeto de la clase Thread, 
al cual se le pasa como parámetro el objeto 
servidor (con lo cual también tiene acceso a sus 
recursos)  - El método run del servidor se ejecuta cuando se 
aplica el método start() sobre el objeto Thread 
recién creado.  
  13Ejemplo implementar Runnable
- Ver (y ejecutar) programa NoSincron.java 
 - De esta forma se comparte obligadamente los 
recursos del servidor entre todos los procesos 
esclavos  - De la otra forma es más bien una opción, (pasar 
un puntero al servidor cuando se crea un objeto 
thread)  - De cualquier forma, será frecuente el compartir 
recursos y por lo tanto la admistración de ellos 
es importante  
  14Regiones críticas y semáforos en Java
- Java provee estos dos mecanismos para controlar 
elacceso a datos compartidos de modo que haya un 
solo tread ejecutando un pedazo de código  - Se puede declarar un método enterocomo región 
crítica (ver sincron1)  - Se puede usar el semáforo que cada objeto posee 
(ver sincron2)  
  15Cómo usar threads para hacer servidores 
concurrentes 
- Hacer una clase Thread que tenga como variables 
de un objeto un socket y flujos de entrada y/o 
salida.  - Programar el constructor de modo que reciba como 
parámetro un socket y haga todo lo necesario para 
dejar inicializado el ambiente para empezar a 
atender al cleinte (por ejemplo, abrir flujos de 
datos de entrada y/o salida del socket recibido)  - Programar el método run de modo que implemente el 
protocolo necesario.  - Programar un método main que en un ciclo infimito 
se ponga a escuchar en un port dado la llegada de 
clientes.  - Con cada cliente nuevo crear un thread nuevo y 
pasar como parámetro el socket  
MultiFileServer
MultiFileThread 
 16Programemos algo bien simple
Bla bla from keyboard
Bla bla
Talk Server
Talk client 
 17Programemos algo no tan simple
Bla bla
Talk client
Talk Server
Talk client
Talk Server
Bla bla
-  Cualquiera puede iniciar la llamada 
 -  Cuando esta contestando no puede llamar 
 -  Cuando está llamando no puede contestar 
 -  Por ahora, sólo el servidor puede mandar 
mensajes