sisoputnfrba / foro

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

Select con multiples conexiones por diferentes puertos #640

Closed memartello closed 7 years ago

memartello commented 7 years ago

Hola, Tengo una duda en el kernel, nos recomendaron crear un solo FD para handlear las conexiones de la cpu y la consola de programas. Mi duda es como incluir todo en el mismo FD, iterarlo y saber que conexion aceptar (porque necesitas saber que socket te la mando)

Saludos!

fededri commented 7 years ago

Recomendaron combinar los dos servidores multiplexados en uno solo, no crear un solo socket, a mi modo de ver y digo esto sin haberlo implementado ni probado podes agregar los dos sockets de escucha de cada puerto al set de sockets y estar escuchando los cambios en ambos sockets. Lo que si me gustaria saber es si realmente vale la pena hacer todo en un solo select teniendo en cuenta que se penaliza a otras operaciones

iago64 commented 7 years ago

@matutex693 Que tal? No estuve presente pero entiendo que lo que dijeron es, en el Kernel, tengan un solo socket escucha y que ahi se conecte todo, despues cuando te llega una conexión haces un handshake para saber si es una consola o una CPU. Por otra parte, no se olviden que el único socket que crean uds en el server de manera explicita y consciente es el socket de escucha, los demás sockets se les van creando por la acción de la función accept().

Por ultimo, no se preocupen por la "performance" porque les pedo asegurar que el aceptar un cliente, hacer el handshake y agregarlo a un FD_SET, les va a tomar menos que a uds apretar 2 veces el enter e iniciar 2 consolas, no s olviden que estamos hablando por un lado de tiempos de Maquina que están en Milisegundos y tiempos hombre que están en el orden de los Segundos

nicozar95 commented 7 years ago

Buenas El tema va de la mano que le metimos 2 puertos para 2 clientes distintos (CPU y CONSOLA) en el Kernel. Aca hay un tema, un par de grupos usaron hilos para tener 2 select con sus "bolsas de file descriptos" diferentes en cada uno, porque no pudieron meter ambas bolsas en un solo select(). Si vos queres que tu select maneje 2 tipos de conexiones de puertos distintos tendrias que tener algo como esto:


// Ponele que por aca te creas los sockets de escucha para CONSOLA Y CPU respectivamente
//llamemoslo bolsaConsola y bolsaCPU, siempre me gusto pensar el select como una bolsa de 
//sockets ¯\_(ツ)_/¯
.
.
//Aca meto las 2 bolsas en una
FD_ZERO(&bolsaAEscuchar);
FD_SET(bolsaConsola, &bolsaAEscuchar);
FD_SET(bolsaCPU, &bolsaAEscuchar);
.
.
//Aca arranca la joda con el select
int retorno;
for(;;){
  retorno = select(.,&bolsaAEscuchar,...) //Los demas campos son los mismos que cualquier select
  if(retorno < 0 ){
    //FALLO
  } else {
    //Aca va la papa del asunto
    //El FD_ISSET me dice en que bolsa de fd esta pasando algo
    if (FD_ISSET(bolsaCPU, &bolsaAEscuchar))
          {
           //Algo esta pasando por el puerto CPU   
          }
    if (FD_ISSET(bolsaConsola, &bolsaAEscuchar))
          {
          //Algo esta pasando por el puerto CONSOLA       
          }
  }
}

Masomenos es algo parecido, no queria meter mucho codigo pero una idea asi es. Ahora bien no estoy seguro si esta mal hacerlo con 2 selects que escuchen en hilos distintos, es otro punto de vista.¿Que ventajas me da tener todo en un solo proceso frente a los 2 hilos?¿Tendre problemas de concurrencia o de condicion de carrera? ¿De qué color será un camaleón mirándose en un espejo? Son preguntas copadas que estaria bueno ir planteandolas y discutiendolas por este issue o en la cursada :smile:

Edit: Tengo miedo que se pierdan con el tema de las bolsaCPU y bolsaCONSOLA, seria su "listening socket"

jhonSalazar commented 7 years ago

Buenas,

Yo hice algo similar, el único inconveniente por así decirlo es que primero espera la señal de quien puse primero en la bolsa, en mi caso la CPU, si trato de conectarme primero con la consola, se me bloquea la conexión hasta que ingresa la CPU, luego de haberme conectado con la CPU, empieza aceptar conexiones de cualquier de los 2.

Saludos.

fededri commented 7 years ago

Yo lo implemente tal cual dijo @nicozar95 , metes los dos listeners en el set a escuchar por el select y funciona bien, yo lo habia hecho con dos hilos, cada uno levantando un servidor multiplexado pero me iba a dar un par de problemas.

LeonelCurti commented 7 years ago

Pero dos listener con dos bind funcionarian sin bloquearse?

nicozar95 commented 7 years ago

Buenas

Los 2 sockets listening que genero en la bolsa a escuchar del select tienen puertos distintos, entonces el sistema los bindea en puertos distintos.

Siempre y cuando estes bindeando a puertos distintos no deberias tener problemas (y siempre fijandote que no te quede el puerto colgado con algo como: setsockopt()) al select le importa poco y nada como esten los listening o en que puerto esten bindeados, el analiza ese conjunto de fd que vos le pasas. Es mas, creo no estoy seguro, que si en vez de setearle sockets le seteas archivos de texto comun y corriente se manejaria igual, seria algo lindo de probar si les sobra tiempo.

El listening no es una funcion bloqueante, creo que te devuelve el socket de una, y en papel el select es un mecanismo no-bloqueante para manejar sockets ¿Pero el select se bloquea igual? Eso tienen que ver a como seteamos los flags del select, generalmente hay un flag que es timeout que es el intervalo de bloqueo en el select, nosotros por lo general lo mantenemos en NULL que nos mantiene el select bloqueante por un tiempo indeterminado. (Creo que era masomenos eso lo que hacia esa flag, cualquier cosa se que @gastonprieto la tiene 100 vaces mas clara que yo en este tema :sweat_smile: ).

varas-c commented 7 years ago

El ultimo parametro de select es un struct de tipo "Timeval" y cumple con lo que decis.

Ese struct tiene 2 campos, un campo "tv_sec" que es "segundos a esperar antes de desbloquearse" y otro tv_usec que es lo mismo pero en microsegundos.

Asi que si a select le pasas un struct timeval seteado en no se, N segundos, select se va a quedar esperando hasta que un evento ocurra O hasta que se terminen los N segundos que le seteaste (lo que ocurra primero).

Se puede usar en el TP siempre y cuando "lo uses bien" y realmente entiendas o puedas justificar por qué le setteastr un timeout.

Si mi memoria no me falla, asi funciona.

Para mas info http://man7.org/linux/man-pages/man2/select.2.html

On May 1, 2017 7:52 PM, "Nicolas Zarewsky" notifications@github.com wrote:

Buenas

Los 2 sockets listening que genero en la bolsa a escuchar del select tienen puertos distintos, entonces el sistema los bindea en puertos distintos.

Siempre y cuando estes bindeando a puertos distintos no deberias tener problemas (y siempre fijandote que no te quede el puerto colgado con algo como: setsockopt()) al select le importa poco y nada como esten los listening o en que puerto esten bindeados, el analiza ese conjunto de fd que vos le pasas. Es mas, creo no estoy seguro, que si en vez de setearle sockets le seteas archivos de texto comun y corriente se manejaria igual, seria algo lindo de probar si les sobra tiempo.

El listening no es una funcion bloqueante, creo que te devuelve el socket de una, y en papel el select es un mecanismo no-bloqueante para manejar sockets ¿Pero el select se bloquea igual? Eso tienen que ver a como seteamos los flags del select, generalmente hay un flag que es timeout que es el intervalo de bloqueo en el select, nosotros por lo general lo mantenemos en NULL que nos mantiene el select bloqueante por un tiempo indeterminado. (Creo que era masomenos eso lo que hacia esa flag, cualquier cosa se que @gastonprieto https://github.com/gastonprieto la tiene 100 vaces mas clara que yo en este tema 😅 ).

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/sisoputnfrba/foro/issues/640#issuecomment-298453797, or mute the thread https://github.com/notifications/unsubscribe-auth/ARPXldrL4sJRj_dZViiW7NEl5JtiCvNyks5r1mIsgaJpZM4M-ugN .

tferraro commented 7 years ago

Buenasss, para ampliar lo que dijeron @nicozar95 y @varas-c, 2 cositas:

Primero, si, es posible pasarle en el set de FD, FD de archivos comunes, e incluso, stdin y stdout, esa es la gran ventaja de que todos tengan la misma interfaz ;).

Algo más, traten de no usar el timeout del select. Los casos en los que tiene sentido utilizarlo son muy acotados y en el 98% de los casos termina generando una espera activa encubierta. Cabe resaltar como bien dijimos en las charlas, TP que demuestra una espera activa, es un TP que en un principio no está para ser aprobado, sin importar que las demás pruebas hayan sido corridas correctamente.

Besis.