Estoy tratando de razonar sobre cómo un servidor simple implementado en C con sockets puede manejar clientes concurrentes. Digamos que un servidor simple espera que un cliente se conecte y luego lee un mensaje enviado por el cliente. read() es una función de bloqueo, por lo que el servidor se bloqueará hasta que un cliente escriba en él. Si asumimos que dos clientes están escribiendo simultáneamente en el servidor. El servidor despertará a uno de ellos, pero ¿qué pasará con el otro? ¿El servidor sigue "escuchando" mientras maneja la solicitud del primer cliente? Sé que la función bind toma un int como segundo argumento que especifica el trabajo pendiente (5 por defecto). ¿Eso significa que solo 5 clientes pueden conectarse simultáneamente a un servidor? Si eso es cierto, ¿cómo se implementan los servidores que manejan múltiples conexiones simultáneas?
Las llamadas al sistema select(2) y poll(2) se inventaron para hacer frente a esta situación exacta (con non-blocking sockets ).
Luego hay un enfoque multiproceso con fork(2) y luego, por supuesto, el servidor podría implementarse con hilos .
La mejor solución para su caso depende de sus requisitos específicos.
Deberías hilos. Por lo general, los servidores tienen un hilo principal que escucha la conexión. Si se realiza una conexión, el subproceso principal crea otro subproceso y pasa esa conexión al subproceso recién creado. De esta manera, las conexiones se responden mientras el subproceso principal aún puede escuchar nuevas conexiones.
Editar: Aquí está el listen():
listen(int socket_fd, int backlog)
Para un socket de escucha dado, el núcleo mantiene dos colas.
usando esta función en el servidor:
int listen(int sockfd, int backlog);El 'retraso' indica cuántos clientes pendientes pueden estar intentando conectarse a la vez.
Cuando esta función devuelve:
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);luego inmediatamente, pasando el parámetro 'sockfd' al
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);para que el subproceso maneje la comunicación con el cliente.
Nota: la creación de un subproceso es costosa y lenta, por lo que inicialmente se debe crear un "grupo" de subprocesos y activar uno para cada conexión del cliente y cuando el cliente se desconecte, devolver el subproceso al grupo.