Práctico 3 - Ejercicio 8

Práctico 3 - Ejercicio 8

de Eliana Rosselli Orrico -
Número de respuestas: 6

Buenas, 

Tengo una duda sobre el ejercicio 8 del práctico 3, parte a). No estaría pudiendo resolver la parte del programa del servidor para las conexiones UDP. No me queda claro cómo enviar los frames y además al mismo tiempo fijarse que se haya recibido una solicitud del cliente en los últimos 90 segundos. Se me ocurrió que capaz con dos threads distintos, pero si el que chequea que se recibe una solicitud del cliente cada 90 segundos cierra la conexión porque no recibió nada, como se "entera" el otro thread de que debe dejar de enviar los frames de video? 

Muchas gracias y saludos

En respuesta a Eliana Rosselli Orrico

Re: Práctico 3 - Ejercicio 8

de Leonardo Alberro Zimmermann -
Hola,

La arquitectura con dos hilos que mencionas es válida. Para que los threads "se enteren" de estas cosas deberías usar memoria compartida o variables globales (con los cuidados de concurrencia adecuados, normalmente simplificados a un mutex.lock mutex.unlock). En este caso una lista global con los suscriptores puede ser de ayuda.

Saludos

En respuesta a Leonardo Alberro Zimmermann

Re: Práctico 3 - Ejercicio 8

de Alfredo Jose Espasandin Mederos -

Hola, ¿podría ser así una sintaxis apropiada?

now = gettime()
if (now - cliente.time) > 90 then
     mutex.lock()
     borrar (lista_clientes, cliente)
     mutex.unlock()

En respuesta a Alfredo Jose Espasandin Mederos

Re: Práctico 3 - Ejercicio 8

de Juan Ramirez -

Buenas,


Como es el caso de UDP vos no vas a tener un clientSock como en TCP, sino que vas a tener la IP y puerto del cliente.


No precisas un thread aparte por cada cliente, basta con el thread principal. Cada vez que te llega un pedido de renovación tendrías que actualizar al timestamp en alguna estructura de datos (asumo que tu estructura es lista_clientes, y que cliente de alguna manera representa la ip y el puerto.


Entonces, si te llega un pedido de "renovación" y ese cliente no tenias registrado a ese cliente, levantarías un thread que, antes de enviar cada frame, ejecutaría el código que pasteaste.


Entonces, en el thread principal hay algo así:


datagram, ip, port = skt.receive();
mutex.lock()
cliente = find(lista_clientes, (ip, port)) # asumo que la tupla ip,port es la clave
if cliente = nil:
    cliente = Cliente(ip, port, gettime())
    lista_clientes.push(cliente)
    threading.new(handle_client, cliente)
else
    cliente.time = gettime()
mutex.unlock()


Una cosa que hice diferente en el thread es que en vez de chequear en cada paso del loop, lo hacía cada aproximadamente 30 segundos para así evitar mucho context-switch pero eso ya es hilar medio fino.

En respuesta a Juan Ramirez

Re: Práctico 3 - Ejercicio 8

de Leonardo Alberro Zimmermann -

Buenas,

solo un comentario. El servidor está haciendo un streaming de video, por lo que cada vez que tenga un frame, deberá enviar ese frame a todos los clientes activos. Con esto dicho, habría que evaluar si es mejor tener un hilo por cliente (y que compitan por el frame) o simplemente tener un hilo que haga el streaming a todos los de la lista cada vez que haya un frame para enviar. Para esto, deberán pensar que pasa con los recursos del servidor cuando los clientes aumentan y que pasa con el delay del envío de los frames en estos enfoques.

Leonardo

En respuesta a Leonardo Alberro Zimmermann

Re: Práctico 3 - Ejercicio 8

de Juan Ramirez -

Hola Leonardo,


Entiendo por donde viene tu comentario: Tener un thread por cliente no escala, no solo por tema de recursos sino porque en promedio a cada cliente le tocaría 1/N del video (yo no había entendido esta parte). Pero tener un thread solo tiene el problema de que el último cliente de la lista va a tener un delay importante en comparación con el primero.


Aprovecho y te consulto:


Se puede asumir que el tiempo que lleva ejecutar el sendto es despreciable para el caso de UDP?



Resumiendo, se me ocurre que la solución más simple sería tener:


* Un thread para el accept TCP, agrega algo del estilo (tcp, socket, now()) a la lista de clientes

* Un thread para aceptar requests UDP, agrega alg del estilo (udp, ip, port, now()) a la lista de clientes

* Un thread que lee frames y los envía a todos los clientes (UDP o TCP) registrados


Capaz que con esto se cumple con el objetivo del ejercicio pero, si quisiéramos achicar el delay, capaz que podríamos contar con un pool de M threads donde cada hilo se encarga de enviarle los frames a N/M clientes.


Vale la pena complicarse con eso para este ejercicio?


En respuesta a Juan Ramirez

Re: Práctico 3 - Ejercicio 8

de Leonardo Alberro Zimmermann -

Hola Juan, va entre líneas >>>

Entiendo por donde viene tu comentario: Tener un thread por cliente no escala, no solo por tema de recursos sino porque en promedio a cada cliente le tocaría 1/N del video (yo no había entendido esta parte). Pero tener un thread solo tiene el problema de que el último cliente de la lista va a tener un delay importante en comparación con el primero.

>>> Correcto, también podrías complicarte tratando de asegurar que el frame se envíe a todos.


Se puede asumir que el tiempo que lleva ejecutar el sendto es despreciable para el caso de UDP?

>>> A diferencia de TCP, UDP no asegura la llegada del segmento, por lo que no es descabellado pensar que el sento no demoraría los envíos.


Resumiendo, se me ocurre que la solución más simple sería tener:

* Un thread para el accept TCP, agrega algo del estilo (tcp, socket, now()) a la lista de clientes

* Un thread para aceptar requests UDP, agrega alg del estilo (udp, ip, port, now()) a la lista de clientes

* Un thread que lee frames y los envía a todos los clientes (UDP o TCP) registrados

>>> Tiene sentido. Solo agregar que el último thread deberá controlar en cada envío que la suscripción esté renovada.


Capaz que con esto se cumple con el objetivo del ejercicio pero, si quisiéramos achicar el delay, capaz que podríamos contar con un pool de M threads donde cada hilo se encarga de enviarle los frames a N/M clientes.

Vale la pena complicarse con eso para este ejercicio?

>>> No, pero es un buen ejercicio para que vean que estos problemas existen y hay que evaluar que solución nos conviene más. Como dice la letra, este ejercicio es del Obligatorio 2 del 2017, por lo que al implementar esto en un lenguaje como C se ve mejor  como afectan estas desiciones. 


Saludos