Hola a todos, resulta que tenía la duda de si era necesario ajustar el socket para que fuera no bloqueante antes de suscribirlo a una llamada select. Buscandome me encontre con esto:
https://stackoverflow.com/questions/16628743/should-socket-be-set-non-blocking-before-it-is-polled-by-select
Me queda claro la razón por la cual debe ser no bloqueante pero realmente vale la pena seguir ese consejo, al menos en el caso de conexiones TCP. Es decir:
Yo tengo un select a la espera de que varias conexiones TCP esten listas para ser leidas, me surte el problema de que se me notifica de que el socket esta listo para lectura, entonces prosigo a intentar hacer la lectura con el respectivo método, sin tener conocimiento de que fue un fallo y el contenido fue descartado por algo como que fallo el checksum(situación que menciona la respuesta del link), esto me va ocasionar distintos comportamientos dependiendo si el socket es bloqueante...
1. Si es bloqueante, entonces mi hilo estara bloqueada esperando que realmente la conexión tenga información entrante, pero este tiempo bloqueado creo que es aceptable debido a que es TCP, entonces tengo la certeza de que habrá una retransmisión en un rango de tiempo relativamente corto. Sin embargo se podría presentar el mismo problema de que el siguiente envio tuviera el mismo problema, ¿acaso se tiene la seguridad de que el kernel va ser capaz de quitar la información entrante erronea(que no cumplio con el checksum) antes de que la función recv recolecte los datos?, agregando a esta solución si quisiera asegurar que el tiempo de bloquea no sea mayor a N porción de segundo, podria agregar:
Al final podría decidir que si pasa el timeout, entonces vuelva a bloquearme en el select.
Nota. Aquí surge una duda de como es que select se da cuenta que un socket esta listo. Puede ser que lo determine conforme solo a si tiene alguna actividad relacionada con el, sin que esto realmente tenga como consecuencia que algo se este poniendo en la cola de entrada, esto respondería la pregunta de por que se notifica como que el socket esta listo cuando realmente no se ha terminado de confirmar la información entrante.
2. Si no es bloqueantes, entonces es cierto que una llamada recv no me bloquearía pero ¿no tendría que hacer todo un mecanismo para asegurarme de recolectar todo el contendio de esa petición? a través de algo como recibe hasta que no encuentres el final de la respuesta, mientras no encuentres el final de la respuesta repite:
sin embargo me da la sensación de que se degradaría mas el desempeño de la aplicación por ese sleep, debido a que ese hilo no tendría ninguna otra tarea que hacer, seria algo parecido a una espera ocupada deficiente.
Vi una implementación en python que lo hace es suscribir los sockets como NO_BLOQEUANTES al select, posterior a eso cuando se le notifica que alguno esta listo, lo cambia para que sea BLOQUEANTE pero finalmente creo que se llega al mismo problema, realmente es una condición de carrera que en algunos casos puede resultar en lo mismo que si siempre fuera BLOQUEANTE. ¿Alguna alternativa u opinión de cual seria la solución ideal?
https://stackoverflow.com/questions/16628743/should-socket-be-set-non-blocking-before-it-is-polled-by-select
Me queda claro la razón por la cual debe ser no bloqueante pero realmente vale la pena seguir ese consejo, al menos en el caso de conexiones TCP. Es decir:
Yo tengo un select a la espera de que varias conexiones TCP esten listas para ser leidas, me surte el problema de que se me notifica de que el socket esta listo para lectura, entonces prosigo a intentar hacer la lectura con el respectivo método, sin tener conocimiento de que fue un fallo y el contenido fue descartado por algo como que fallo el checksum(situación que menciona la respuesta del link), esto me va ocasionar distintos comportamientos dependiendo si el socket es bloqueante...
1. Si es bloqueante, entonces mi hilo estara bloqueada esperando que realmente la conexión tenga información entrante, pero este tiempo bloqueado creo que es aceptable debido a que es TCP, entonces tengo la certeza de que habrá una retransmisión en un rango de tiempo relativamente corto. Sin embargo se podría presentar el mismo problema de que el siguiente envio tuviera el mismo problema, ¿acaso se tiene la seguridad de que el kernel va ser capaz de quitar la información entrante erronea(que no cumplio con el checksum) antes de que la función recv recolecte los datos?, agregando a esta solución si quisiera asegurar que el tiempo de bloquea no sea mayor a N porción de segundo, podria agregar:
Código (c) [Seleccionar]
setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof timeout);
Al final podría decidir que si pasa el timeout, entonces vuelva a bloquearme en el select.
Nota. Aquí surge una duda de como es que select se da cuenta que un socket esta listo. Puede ser que lo determine conforme solo a si tiene alguna actividad relacionada con el, sin que esto realmente tenga como consecuencia que algo se este poniendo en la cola de entrada, esto respondería la pregunta de por que se notifica como que el socket esta listo cuando realmente no se ha terminado de confirmar la información entrante.
2. Si no es bloqueantes, entonces es cierto que una llamada recv no me bloquearía pero ¿no tendría que hacer todo un mecanismo para asegurarme de recolectar todo el contendio de esa petición? a través de algo como recibe hasta que no encuentres el final de la respuesta, mientras no encuentres el final de la respuesta repite:
Código (c) [Seleccionar]
recv(....);
sleep(algunos_milisegundos);
sin embargo me da la sensación de que se degradaría mas el desempeño de la aplicación por ese sleep, debido a que ese hilo no tendría ninguna otra tarea que hacer, seria algo parecido a una espera ocupada deficiente.
Vi una implementación en python que lo hace es suscribir los sockets como NO_BLOQEUANTES al select, posterior a eso cuando se le notifica que alguno esta listo, lo cambia para que sea BLOQUEANTE pero finalmente creo que se llega al mismo problema, realmente es una condición de carrera que en algunos casos puede resultar en lo mismo que si siempre fuera BLOQUEANTE. ¿Alguna alternativa u opinión de cual seria la solución ideal?