Håndtering af flere klienter
select og poll
Håndtering af flere klienter er en gratis C Academy-lektion på CoddyKit. Dette er lektion 4 af 4. Du kan læse hele lektionen gratis nedenfor — og derefter øve dig praktisk i browseren med en indbygget kodeeditor og en AI-vejleder, der er tilgængelig døgnet rundt. Den er en del af læringsforløbet i C Academy, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. C Academy-kurset indeholder 4 lektioner i alt.
Problemet med samtidighed
En simpel server håndterer én klient ad gangen. Hvis en klient er langsom, må alle andre vente. Hvis du vil betjene mange klienter samtidigt, skal du bruge en anden model.
Metoder til samtidighed
Tre almindelige strategier:
- En tråd eller proces pr. klient: enkelt, men ressourcekrævende i stor skala
- I/O-multipleksing med
selectellerpoll: én tråd overvåger mange sockets - Hændelsesløkker med
epoll/kqueue: skalerer til tusindvis
Hvad select gør
select() overvåger et sæt fildeskriptorer og fortæller dig, hvilke der er klar til læsning eller skrivning, eller hvilke der har fejl, alt sammen i ét blokerende kald. Det gør det muligt for én tråd at betjene mange sockets.
Grundlæggende om fd_set
select bruger en bitmaske af typen fd_set. Du administrerer den med makroerne FD_ZERO, FD_SET, FD_CLR og 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 */
}Kald af select
select skal have den højeste fd plus én og ændrer sættet direkte for at markere deskriptorer, der er klar. Da kaldet er destruktivt, skal du opbygge sættet igen før hvert kald.
#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 */
}Serverløkken med select
Mønstret er: opbyg sættet igen, kald select, og behandl derefter hver fd, der er klar: acceptér enten en ny klient (hvis det er lytter-deskriptoren), eller læs data (hvis det er en klient).
#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 */
}
}
}Sporing af klienter
Når du accepterer en ny forbindelse, skal du føje dens fd til hovedsættet og opdatere maxfd. Når en klient afbryder forbindelsen (recv returnerer 0), skal du køre close på den og fjerne den fra sættet med 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);
}Begrænsninger ved select
select har flere ulemper:
- Begrænset til
FD_SETUP-deskriptorer (ofte 1024) - O(n)-gennemgang af alle fd'er ved hvert kald
- Sættet skal opbygges igen ved hver iteration
Ved mange forbindelser skalerer poll eller epoll bedre.
Hvad poll tilbyder
poll() bruger et array af struct pollfd i stedet for en fast bitmaske. Derfor har den ingen grænse på 1024 deskriptorer, og den ødelægger ikke inputtet ved hvert kald.
#include <poll.h>
void setup_poll(struct pollfd *pfd, int listen_fd) {
pfd[0].fd = listen_fd;
pfd[0].events = POLLIN; /* notify when readable */
}Kald af poll
poll blokerer, indtil mindst én fd er klar (eller tidsfristen udløber), og sætter derefter revents for hver post, der er klar.
#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;
}Opskalering med epoll
Ved tusindvis af forbindelser leverer Linux' epoll (og BSD's kqueue) kun de deskriptorer, der er klar, i O(1) pr. hændelse. Dermed undgås den fulde gennemgang, som select og poll udfører.
Hurtigt tjek
Test din forståelse af håndtering af flere klienter.
Opsummering
Du har lært at betjene mange klienter med én tråd.
selectovervåger mange fd'er; administrér dem med FD_-makroer- Opbyg sættet igen i hver løkke, fordi select er destruktiv
- Føj accepterede klienter til sættet, og fjern dem ved afbrydelse
pollundgår grænsen på 1024;epollskalerer til tusindvis
Lær C med en AI-underviser — gratis
Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.
- Kurser
- 39
- Lektioner
- 144
Ofte stillede spørgsmål
Er lektionen “Håndtering af flere klienter” gratis?
Ja — hele teksten til “Håndtering af flere klienter” kan læses gratis her på nettet. Hvis du vil øve dig interaktivt med en indbygget kodeeditor og en AI-vejleder døgnet rundt og få adgang til resten af C Academy-kurset, skal du opgradere til CoddyKit PRO. C Academy-kurset indeholder 4 lektioner i alt.
Hvad lærer jeg i “Håndtering af flere klienter”?
select og poll Du øver dig i C Academy med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.
Skal jeg have erfaring for at begynde på C Academy?
Der kræves ingen tidligere erfaring. C Academy på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 4 af 4.
Hvor lang tid tager lektionen “Håndtering af flere klienter”?
De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.
Kan jeg skrive og køre kode i denne C Academy-lektion?
Ja. Alle C Academy-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.
Alle lektioner i dette kursus
- Oversigt over sockets
- TCP-server
- TCP-klient
- Håndtering af flere klienter