C Academy · Lektion

Håndtering af flere klienter

select og poll

Lektion 4 af 413 trin

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 select eller poll: é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.

  • select overvå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
  • poll undgår grænsen på 1024; epoll skalerer til tusindvis
Gratis at komme i gang

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

  1. Oversigt over sockets
  2. TCP-server
  3. TCP-klient
  4. Håndtering af flere klienter
← Tilbage til C Academy