El Martes, 26 de Agosto de 2008 01:16, Leandro Lucarella escribió: > Herr Groucho, el 25 de agosto a las 11:35 me escribiste: > > Hola. > > Para resolver un problema, se me ha planteado la necesidad de > > hacer un programa que acepte conexiones TCP desde equipos > > embebidos y les lea datos que dichos equipos están recabando en > > campo. > > > > Actualmente el programa de esos equipos embebidos establece la > > conexión TCP y la mantiene conectada todo el tiempo. Entonces el > > servidor que acepta esas conexiones va a tener un socket > > conectado con cada equipo todo el tiempo. Si hay 10 equipos, > > tendrá 10 conexiones abiertas. Pero qué pasa cuando hay 10000 > > equipos y por lo tanto 10000 conexiones? > > Nada, no debería pasar nada. > > > El programa que va a aceptar las conexiones actualmente lanza un > > proceso hijo por cada conexión que acepta. Eso tiene la ventaja > > de que el tratamiento de TCP/IP y la implementación del protocolo > > de aplicación se simplifica (sólo hay un socket del cual > > preocuparse y si el protocolo de aplicación tiene que esperar un > > evento, directamente se puede bloquear en un read() o write() o > > irse a dormir con timeout en un select()). Con 10000 conexiones, > > tendría 10001 procesos. Es esta una estrategia cuerda para > > manejar 10000 conexiones? > > No. Para qué querés tener 10001 procesos si con uno alcanza y > sobre.
Porque no quiero tener un arreglo de 10000 file descriptors, no sé si select() o poll() pueden monitorear tal cantidad de file descriptors (creo que no), y porque estaba bueno escribir el código del protocolo de comunicación en forma secuencial (te mando esto, me duerno hasta que contestes. Me fijo que contestaste, te respondo tal cosa y me duermo de nuevo, etc.) en lugar de por eventos y estados (en el socket 2182 ya mandé la preguta, en el 5748 todavía no. Ok, la mando y me acuerdo de que ya la mandé. Vino un paquete. En qué socket? El 9023. Ah, en ese ya había mandado la pregunta, e iba por el segundo intento. Ahora funcionó? Sí, bien. Va la siguiente pregunta y vuelvo a 0 la cuenta de reintentos y me acuerdo que voy por la segunda pregunta, etc.). > > - El sistema operativo soportará 10000 procesos (hace unos años > > el tamaño de la tabla de procesos era elegido en tiempo de > > compilación del kernel, en valores miserables como 200)? > > No los necesitás. Vos me estás planteando que tenga 10000 instancias independientes del protocolo de aplicación (o bueno, las que yo quiera, no necesito hablar a la vez por todos los sockets) y atienda todo en un programa de un solo thread, o en un programa con un thread independiente para cada instancia del protocolo de comunicación? > > - El stack TCP/IP soportará 10000 conexiones? > Sí > > > - Qué le pasará al consumo de memoria? > Bah... no debería ser muy alto. En qué caso? Cada proceso hijo recibiría un stack propio... y el consumo de memoria se iría a la mierda. > > - Qué le pasará al multitasking si el scheduler tiene que mirar > > una tabla de procesos tan grande cada unas pocas decenas de > > milisegundos? > > No debería pasar nada grave con un scheduler O(1) como el de Linux, > pero los context switches probablemente sí consuman mucho más > procesador del que quisieras. Cómo que O(1)? Es constante el tiempo? Qué mierda hace para que sea constante el tiempo? > > Qué otras estrategias son concebibles? > 1 solo proceso, un solo thread + epoll[1] (o más simple, > libevent[2] o libev[3]). Bibliotecas de alto nivel que no conocía. Bien! > > - Un único proceso que atienda y maneje todas las conexiones, > > usando arreglos para guardar los file descriptors de los sockets, > > select() para esperar que pase algo interesante en alguno de > > ellos e iteraciones por todos lados? > Es la versión ineficiente de lo que propongo =) Ja! > > - Un proceso que lance hijos, cada uno de los cuales maneje unos > > pocos threads (un híbrido entre los 2) > > No creo que tener threads te beneficie en algo, a menos que tengas > más de un core, por supuesto. Me beneficia en el razopnamiento del problema. Cada comunicación es independiente y secuencial. Es mentalmente mucho más simple de modelar la situación con threads que con eventos. Ver más arriba cómo luce la implementación del protocolo con threads/procesos independientes y con eventos. > > Sugerencias? > Usá, libev. En la página hay benchmarks[4] (contra la libevent, > para benchmarks de select/poll vs epoll mirá la página de libevent) > que llegan a los 100.000 fds abiertos con tiempos razonables. > > Para que veas que es totalmente viable esta opción, te adjunto una > implementación pedorra en Python hecha en 15 minutos. Solo tené en > cuenta que tenés que levantar la cantidad máxima de fds abiertos > que podés tener (ulimit -n) porque por default viene en 1024. Ok, buen dato. > Anda bien con los 10000 sockets, usando poll (NO epoll) y en un > lenguaje interpretado. En mi Athlon XP 2200 (1.8GHz) está el CPU > entre 80% y 85% y el load average entre 2 y 8 (con el X abierto con > varias aplicaciones, incluido el puto Firefox que está usando 8% > del CPU vaya uno a saber en qué). Les puse que mande un mensaje > cada 10ms y completa una "ronda" de los 10000 fds en unos 2 > minutos. > > Como verás, lo tuyo es un no-problema... Caramba. El C10K problem es un no-problem... Sos groso, sabelo. Y gracias por los datos. > [1] http://linux.die.net/man/4/epoll > [2] http://monkey.org/~provos/libevent/ > [3] http://libev.schmorp.de/ > [4] http://libev.schmorp.de/bench.html -- Herr Groucho ID Jabber: [EMAIL PROTECTED] Señal distintiva: LU5MJR - 144,550 MHz FM. Clave pública GPG: hkp://pks.lugmen.org.ar Fingerprint GPG: B7BD 0FC7 D9A2 66F3 4EFC 45EE 7DE2 3932 597B 6354
