sisoputnfrba / foro

Foro de consultas para el trabajo práctico
148 stars 7 forks source link

Estado de Conexión en un socket #494

Closed varas-c closed 8 years ago

varas-c commented 8 years ago

Tengo la siguiente duda.

En el checkpoint me comentaron que el mensaje de "Turno Concedido" en el planificador fue eliminado. Es decir, los entrenadores mandan sus pedidos sin esperar un turno, pero sí esperan la respuesta del mapa ante esa solicitud.

Teniamos implementado un metodo de desconexión basado en el Turno Concedido, peero como lo sacaron y lo tuvimos que sacar del codigo, este método ya no es tan efectivo. Como ahora los entrenadores mandan mensajes todo el tiempo sin esperar el turno, mi planificador se entera "tarde" que el entrenador se desconectó.

Mi pregunta es, ¿hay alguna forma de hacer "ping" sobre un socket para ver si el cliente está conectado o no? Se que la forma de ver si un entrenador se desconectó es hacer un recv y ver si los bytes leidos es cero, pero este metodo digamos que "se fija en el mensaje recibido" o sea en el buffer de cada socket. Hay alguna forma de "operar" directamente sobre la conexión? Por ejemplo haciendo un "ping" para ver si el entrenador esta "vivo" o se desconectó, sin ver necesariamente los mensajes que manda.

Espero haber sido claro :) Gracias!

PD: Probamos las funciones getsockopt y getpeername pero ninguna detecta las desconexiones. Info sacada de acá: http://stackoverflow.com/questions/4142012/how-to-find-the-socket-connection-state-in-c

iago64 commented 8 years ago

Buenas buenas, Me parece que le estan dando una vuela innecesaria al tema, ya que el mensaje Turno Concedido les va a fallar porque le estaba por hacer un send a algo que estuviera desconectado, ahora en lugar de decirle desde el mapa:

Espero que no les complique mucho la propuesta de solución. Saludos.-

varas-c commented 8 years ago

@iago64 Gracias por la respuesta. No entiendo bien lo que me intentaste explicar, pero creo que no llega a solucionar mi inconveniente

Como ya no hay turno, los entrenadores al conectarse no esperan a que el mapa les diga "dale, mandame tu mensaje", o sea el entrenador ni bien se conecta, manda su mensaje de "Quiero una Pokenest" y esperará X quantum a que el mapa le atienda el pedido que ya mandó. O sea ese pedido queda "guardado" en el buffer del socket hasta que el planificador lo agarre y lea ese mensaje.

¿Pero que pasa si el entrenador manda una solicitud de Pokenest y se desconecta inmediatamente? El mensaje que manda es "Quiero una Pokenest" y "Quiero desconectarme". El planificador, cuando sea el turno de dicho entrenador, va a leer que el entrenador Quiere una Pokenest, y va a decir "Tomá acá esta tu pokenest" pero como se desconectó, el send me va a decir "El entrenador se desconectó" (creo, no estoy seguro de esto) por lo que ahí puedo detectar que el entrenador se fue y lo desconecto

Pero que pasa? El planificador tiene que esperar a que sea el turno de ese entrenador, leer su mensaje y ahi recien va a darse cuenta que se fue. El problema es ese. Que pasa si éste entrenador se desconectó hace 10,20 o 30 quantums? Es necesario esperar tanta cantidad de quantums para darme cuenta que se desconectó?

Por eso estaba buscando una forma de ver si el entrenador está conectado o no, sin importar los mensajes que manda. Una forma que habiamos encontrado era hacer un recv con un flag MSG_PEEK para ver que hay en el buffer, pero si en el buffer hay dos mensajes de "Quiero Pokenest" y "Quiero desconectarme", la cantidad de Bytes leidas es mayor a cero, por mas que el entrenador haya mandado el mensaje de desconectarse.

Esa es nuestra duda y no sabemos como solucionarlo :/ Gracias!

varas-c commented 8 years ago

Cuando estaba el mensaje de TurnoConcedido, los entrenadores no podian mandar mensajes sin que el planificador les de el turno, por lo que hacer un recv y ver si la cantidad de bytes era 0, era bastante sencillo. Pero ahora, no encontramos forma de solucionarlo

iago64 commented 8 years ago

Efectivamente, estas pensándolo bien: Cuando el entrenador se conecte y diga: "Quiero la pokenest X" el mapa lo va a dejar ahí planificado hasta que le toque, si el entrenador atras de eso manda otro mensaje y se desconecta cuando el mapa le quiera mandar un La pokenest esta en X lugar o decirle te moviste a tal posición el send te va a fallar y ahi es donde tu proceso mapa tiene que decir, el entrenador 1 se desconecto y liberarle los recursos. Y si, pueden pasar 30 turnos hasta que le toque y que recién ahí el mapa se de cuenta que el entrenador se desconecto. La pregunta es, eso esta mal según el enunciado? o simplemente el enunciado dice:

Eventualmente, el Planificador podrá detectar que un Entrenador se desconectó (cumplió los objetivos del Mapa, o murió). Cuando esto ocurra, deberá liberar todos los Pokémons que éste había capturado y, si correspondiera, otorgarlos a los Entrenadores bloqueados por ellos, desbloqueándolos. Al mismo tiempo, el Planificador eliminará al Entrenador de sus listas de Planificación.

https://sisoputnfrba.gitbooks.io/char-mander-tp-2c2016/content/proceso-mapa.html

varas-c commented 8 years ago

Buenisimo :) Hasta acá entendí. El problema es ese, que el entrenador puede estar ahi 30 turnos hasta que lo desconecten. Para nosotros, desde nuestro punto de vista, esto está "mal" porque por ahi este entrenador A tiene un pikachu que lo quiere un entrenador B que está bloqueado. Y como A ya se fue, no es "justo" que B espere 30 quantums esperando a que el planificador desconecte a A, sabiendo que A ya mandó un mensaje de "Quiero desconectarme". Nosotros lo habiamos pensado asi, pero es bastante "laburo" detectar una desconexión "instantanea" digamos o lo mas pronta posible.

Si me decis que está bien que B espere "injustamente" hasta que el planificador se de cuenta que A se desconectó, lo hacemos de esta forma que es mas sencilla pero mas "injusta" digamos.

Gracias!

mgarciaisaia commented 8 years ago

Che, está buenísimo que se te plantee esta duda. La verdad es que, sí, es un caso que cambió bastante con los cambios que hicimos al enunciado. Y hasta ahora, al menos a mí, no se me ocurrió cómo mejorar la situación.

Bah, una opción es implementar una cola de mensajes en tu Mapa. Tenés un hilo que se dedica a hacerle recv() constantemente a todos los sockets, y cada vez que recibe un mensaje manda esos bytes a una cola de ese socket, y el hilo que "realmente" tiene que leer los mensajes (el planificador, digamos) lee esa cola en vez del socket. De ese modo, ni bien llega un mensaje lo mandás a otro buffer, y podés seguir haciendo recv() sobre el socket para enterarte al instante de que se cayó la conexión.

De más está decir que ni a palos pretendemos que todos implementen esto. Es parte del tradeoff que elegimos cuando cambiamos el enunciado.

Si algún grupo gustara hacerlo, me encantaría verlo andar (para valores muy esotéricos de me encantaría), pero no es obligatorio ni prioritario en absoluto.

Para cerrar, estas cosas son las que nos gusta charlar en los temibles coloquios. Entender qué consecuencias trajo cada decisión de diseño (tanto nuestras en el enunciado como suyas en la implementación), qué ventajas y desventajas tuvo, y por qué decidieron que la que implementaron sí y las otras alternativas no.

Lindo thread, che :)

varas-c commented 8 years ago

Justamente lo de la cola de mensajes lo había pensado pero, es bastante laburo y laaaaaargo. Habiamos intentado con mi grupo ver formas de verificar si las conexiones seguian abiertas, teniamos varias en mente, como la de la lista de Mensajes que comentas o crear un hilo "chusma" que esté revisando todo el tiempo los mensajes mandados o una forma medio complicada, sería que el mapa envíe paquetes estilo "Ping" que sean ignorados por el jugador

Pero si, es mucho laburo y puede llevar a muchas fallas tambien. Ademas no somos expertos en redes, tcp y esas cosas, por lo que nuestro poco conocimiento nos impedía avanzar con este tema de ver si las conexiones estaban vivas o no y peor, la conexion se puede caer en cualquier momento.

Al final, decidimos hacerlo como comentaron mas arriba :) Igual, por lo menos a mi, me "picó" la curiosidad de saber como hacer esto. Quedará para mas adelante supongo