Mehrere Clients verarbeiten
select und poll
Mehrere Clients verarbeiten ist eine kostenlose C Academy-Lektion auf CoddyKit. Dies ist Lektion 4 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des C Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der C Academy-Kurs umfasst insgesamt 4 Lektionen.
Das Nebenläufigkeitsproblem
Ein einfacher Server verarbeitet jeweils einen Client. Wenn ein Client langsam ist, müssen alle anderen warten. Um viele Clients gleichzeitig zu bedienen, benötigen Sie ein anderes Modell.
Ansätze für Nebenläufigkeit
Drei gängige Strategien:
- Ein Thread/Prozess pro Client: einfach, aber bei hoher Skalierung ressourcenintensiv
- I/O-Multiplexing mit
selectoderpoll: Ein Thread überwacht viele Sockets - Ereignisschleifen mit
epoll/kqueue: skalierbar auf Tausende
Was select macht
select() überwacht eine Gruppe von Dateideskriptoren und teilt Ihnen in einem einzigen blockierenden Aufruf mit, welche zum Lesen oder Schreiben bereit sind oder Fehler aufweisen. Dadurch kann ein Thread viele Sockets bedienen.
Grundlagen von fd_set
select verwendet eine Bitmaske vom Typ fd_set. Verwalten Sie sie mit den Makros FD_ZERO, FD_SET, FD_CLR und 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 */
}select aufrufen
select benötigt den höchsten fd plus eins und verändert die Menge direkt, um bereite Deskriptoren zu markieren. Da der Aufruf destruktiv ist, müssen Sie die Menge vor jedem Aufruf neu aufbauen.
#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 */
}Die select-Serverschleife
Das Muster: Bauen Sie die Menge neu auf, rufen Sie select auf und verarbeiten Sie dann jeden bereiten fd: Entweder akzeptieren Sie einen neuen Client (wenn es der Listener ist) oder lesen Daten (wenn es ein Client ist).
#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 */
}
}
}Clients verwalten
Wenn Sie eine neue Verbindung akzeptieren, fügen Sie deren fd zur Hauptmenge hinzu und aktualisieren Sie maxfd. Wenn ein Client die Verbindung trennt (recv gibt 0 zurück), rufen Sie close auf und entfernen Sie den fd mit FD_CLR aus der Menge.
#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);
}Grenzen von select
select hat einige Nachteile:
- Begrenzt auf
FD_SETUPDeskriptoren (oft 1024) - O(n)-Durchlauf aller fds bei jedem Aufruf
- Die Menge muss bei jeder Iteration neu aufgebaut werden
Für viele Verbindungen skalieren poll oder epoll besser.
Was poll bietet
poll() verwendet ein Array aus struct pollfd statt einer festen Bitmaske. Daher gibt es keine Begrenzung auf 1024 Deskriptoren, und die Eingabe wird bei jedem Aufruf nicht zerstört.
#include <poll.h>
void setup_poll(struct pollfd *pfd, int listen_fd) {
pfd[0].fd = listen_fd;
pfd[0].events = POLLIN; /* notify when readable */
}poll aufrufen
poll blockiert, bis mindestens ein fd bereit ist (oder das Zeitlimit abläuft), und setzt dann revents für jeden bereiten Eintrag.
#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;
}Hochskalieren mit epoll
Für Tausende von Verbindungen liefern Linux' epoll und BSDs kqueue nur die bereiten Deskriptoren mit O(1) pro Ereignis. Dadurch vermeiden sie den vollständigen Durchlauf, den select und poll durchführen.
Schnelltest
Testen Sie Ihr Verständnis der Verarbeitung mehrerer Clients.
Zusammenfassung
Sie haben gelernt, viele Clients mit einem Thread zu bedienen.
selectüberwacht viele fds; verwalten Sie sie mit FD_-Makros- Bauen Sie die Menge in jeder Schleife neu auf, da select destruktiv ist
- Fügen Sie akzeptierte Clients zur Menge hinzu; entfernen Sie sie bei Verbindungsabbruch
pollvermeidet das Limit von 1024;epollskaliert auf Tausende
Häufig gestellte Fragen
Ist die Lektion „Mehrere Clients verarbeiten“ kostenlos?
Ja — der vollständige Text von „Mehrere Clients verarbeiten“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des C Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der C Academy-Kurs umfasst insgesamt 4 Lektionen.
Was lerne ich in „Mehrere Clients verarbeiten“?
select und poll Du übst C Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.
Brauche ich Erfahrung, um C Academy zu starten?
Keine Vorkenntnisse erforderlich. C Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 4 von 4.
Wie lange dauert die Lektion „Mehrere Clients verarbeiten“?
Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.
Kann ich in dieser C Academy-Lektion Code schreiben und ausführen?
Ja. Jede C Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.
Alle Lektionen in diesem Kurs
- Überblick über Sockets
- TCP-Server
- TCP-Client
- Mehrere Clients verarbeiten