0Pricing
C Academy · Lección

Gestión de varios clientes

select y poll

Gestión de varios clientes es una lección gratuita de C Academy en CoddyKit. Esta es la lección 4 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de C Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de C Academy incluye 4 lecciones en total.

El problema de la concurrencia

Un servidor sencillo gestiona un cliente cada vez. Si un cliente es lento, todos los demás esperan. Para atender a muchos clientes simultáneamente, necesita un modelo diferente.

Estrategias de concurrencia

Tres estrategias habituales:

  • Un hilo o proceso por cliente: sencillo, pero pesado a gran escala
  • Multiplexación de E/S con select o poll: un hilo supervisa muchos sockets
  • Bucles de eventos con epoll/kqueue: escala a miles

Qué hace select

select() supervisa un conjunto de descriptores de archivo e indica cuáles están listos para leer o escribir, o cuáles tienen errores, todo ello en una única llamada bloqueante. Esto permite que un solo hilo atienda muchos sockets.

Conceptos básicos de fd_set

select utiliza una máscara de bits fd_set. Gestione esta máscara con las macros: FD_ZERO, FD_SET, FD_CLR y FD_ISSET.

#include <sys/select.h>

void setup_set(fd_set *set, int listen_fd) {
    FD_ZERO(set);          /* clear all */
    FD_SET(listen_fd, set); /* watch the listener */
}

Llamar a select

select necesita el fd más alto más uno y modifica el conjunto directamente para marcar los descriptores listos. Como es destructivo, debe reconstruir el conjunto antes de cada llamada.

#include <sys/select.h>
#include <stdio.h>

int wait_ready(int maxfd, fd_set *read_set) {
    int n = select(maxfd + 1, read_set, NULL, NULL, NULL);
    if (n < 0) perror("select");
    return n; /* number of ready fds */
}

Bucle del servidor con select

El patrón es el siguiente: reconstruya el conjunto, llame a select y, después, para cada fd listo, acepte un cliente nuevo (si es el socket de escucha) o lea los datos (si es un cliente).

#include <sys/select.h>

void loop_skeleton(int listen_fd, fd_set *master, int maxfd) {
    fd_set work;
    for (;;) {
        work = *master;           /* copy, select destroys it */
        select(maxfd + 1, &work, NULL, NULL, NULL);
        for (int fd = 0; fd <= maxfd; fd++) {
            if (!FD_ISSET(fd, &work)) continue;
            /* fd == listen_fd -> accept; else -> recv */
        }
    }
}

Seguimiento de clientes

Al aceptar una conexión nueva, añada su fd al conjunto principal y actualice maxfd. Cuando un cliente se desconecte (recv devuelve 0), haga close y elimínelo del conjunto con FD_CLR.

#include <sys/select.h>
#include <unistd.h>

void add_client(fd_set *master, int *maxfd, int conn) {
    FD_SET(conn, master);
    if (conn > *maxfd) *maxfd = conn;
}
void drop_client(fd_set *master, int conn) {
    close(conn);
    FD_CLR(conn, master);
}

Limitaciones de select

select tiene varios inconvenientes:

  • Está limitado a FD_SETUP descriptores (a menudo 1024)
  • Realiza un recorrido O(n) de todos los fds en cada llamada
  • El conjunto debe reconstruirse en cada iteración

Para muchas conexiones, poll o epoll ofrecen una mejor escalabilidad.

Qué ofrece poll

poll() recibe un array de struct pollfd en lugar de una máscara de bits fija, por lo que no tiene el límite de 1024 descriptores y no destruye la entrada en cada llamada.

#include <poll.h>

void setup_poll(struct pollfd *pfd, int listen_fd) {
    pfd[0].fd = listen_fd;
    pfd[0].events = POLLIN; /* notify when readable */
}

Llamar a poll

poll se bloquea hasta que al menos un fd está listo (o vence el tiempo de espera) y, después, establece revents en cada entrada lista.

#include <poll.h>
#include <stdio.h>

int poll_ready(struct pollfd *pfds, int count) {
    int n = poll(pfds, count, -1); /* -1 = block forever */
    if (n < 0) perror("poll");
    return n;
}

Escalar: epoll

Para miles de conexiones, epoll de Linux (y kqueue de BSD) devuelve únicamente los descriptores listos en O(1) por evento, evitando el recorrido completo que realizan select y poll.

Comprobación rápida

Compruebe su comprensión de la gestión de varios clientes.

Resumen

Ha aprendido a atender a muchos clientes con un solo hilo.

  • select supervisa muchos fds; gestiónelos con las macros FD_
  • Reconstruya el conjunto en cada bucle porque select es destructivo
  • Añada los clientes aceptados al conjunto y elimínelos al desconectarse
  • poll evita el límite de 1024; epoll escala a miles

Preguntas frecuentes

¿La lección «Gestión de varios clientes» es gratis?

Sí — el texto completo de «Gestión de varios clientes» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de C Academy, actualiza a CoddyKit PRO. El curso de C Academy incluye 4 lecciones en total.

¿Qué aprenderé en «Gestión de varios clientes»?

select y poll Practicas C Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.

¿Necesito experiencia previa para empezar C Academy?

No se requiere experiencia previa. C Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 4 de 4.

¿Cuánto tiempo toma la lección «Gestión de varios clientes»?

La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.

¿Puedo escribir y ejecutar código en esta lección de C Academy?

Sí. Cada lección de C Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.

Todas las lecciones de este curso

  1. Introducción a los sockets
  2. Servidor TCP
  3. Cliente TCP
  4. Gestión de varios clientes
← Volver a C Academy