Gestire più client
select e poll
Gestire più client è una lezione C Academy gratuita su CoddyKit. Questa è la lezione 4 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento C Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso C Academy include 4 lezioni in totale.
Il problema della concorrenza
Un server semplice gestisce un client alla volta. Se un client è lento, tutti gli altri devono aspettare. Per servire molti client contemporaneamente, è necessario un modello diverso.
Approcci alla concorrenza
Tre strategie comuni:
- Un thread o processo per client: semplice, ma oneroso su larga scala
- Multiplexing dell'I/O con
selectopoll: un thread controlla molti socket - Event loop con
epoll/kqueue: scalabile fino a migliaia di connessioni
Cosa fa select
select() controlla un insieme di descrittori di file e indica quali sono pronti per la lettura o la scrittura, oppure presentano errori, tutto tramite un'unica chiamata bloccante. In questo modo un thread può servire molti socket.
Nozioni di base su fd_set
select utilizza una maschera di bit fd_set. La gestisca con le macro: FD_ZERO, FD_SET, FD_CLR e 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 */
}Chiamare select
select richiede il descrittore più alto più uno e modifica l'insieme direttamente, contrassegnando i descrittori pronti. Poiché è distruttivo, ricrei l'insieme prima di ogni chiamata.
#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 */
}Il ciclo del server con select
Lo schema è il seguente: ricrei l'insieme, chiami select, quindi, per ogni descrittore pronto, accetti un nuovo client se si tratta del socket in ascolto oppure legga i dati se si tratta di un client.
#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 */
}
}
}Tenere traccia dei client
Quando accetta una nuova connessione, aggiunga il relativo fd all'insieme principale e aggiorni maxfd. Quando un client si disconnette (recv restituisce 0), esegua close e rimuova il descrittore dall'insieme 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);
}Limiti di select
select presenta alcuni svantaggi:
- Limitato a
FD_SETUPdescrittori (spesso 1024) - Scansione O(n) di tutti gli fd a ogni chiamata
- L'insieme deve essere ricreato a ogni iterazione
Per molte connessioni, poll o epoll offrono una scalabilità migliore.
Cosa offre poll
poll() utilizza un array di struct pollfd anziché una maschera di bit fissa, quindi non ha il limite di 1024 descrittori e non distrugge l'input a ogni chiamata.
#include <poll.h>
void setup_poll(struct pollfd *pfd, int listen_fd) {
pfd[0].fd = listen_fd;
pfd[0].events = POLLIN; /* notify when readable */
}Chiamare poll
poll rimane bloccato finché almeno un fd non è pronto (oppure scade il timeout), quindi imposta revents per ogni voce pronta.
#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;
}Scalare: epoll
Per migliaia di connessioni, epoll di Linux (e kqueue dei sistemi BSD) restituisce solo i descrittori pronti in O(1) per evento, evitando la scansione completa eseguita da select e poll.
Verifica rapida
Verifichi la Sua comprensione della gestione di più client.
Riepilogo
Ha imparato a servire molti client con un solo thread.
selectcontrolla molti fd; li gestisca con le macro FD_- Ricrei l'insieme a ogni ciclo perché select è distruttivo
- Aggiunga i client accettati all'insieme; li rimuova alla disconnessione
pollevita il limite di 1024;epollè scalabile fino a migliaia di connessioni
Domande Frequenti
La lezione «Gestire più client» è gratuita?
Sì — il testo completo di «Gestire più client» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso C Academy, passa a CoddyKit PRO. Il corso C Academy include 4 lezioni in totale.
Cosa imparerò in «Gestire più client»?
select e poll Eserciti C Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.
Ho bisogno di esperienza per iniziare C Academy?
Non è richiesta alcuna esperienza precedente. C Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 4 di 4.
Quanto tempo richiede la lezione «Gestire più client»?
La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.
Posso scrivere ed eseguire codice in questa lezione C Academy?
Sì. Ogni lezione C Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.
Tutte le lezioni di questo corso
- Panoramica dei socket
- Server TCP
- Client TCP
- Gestire più client