C Academy · leksjon

En enkel ekkotjener

Betjen mange klienter samtidig.

Leksjon 4 av 413 trinn

En enkel ekkotjener er en gratis leksjon i C Academy på CoddyKit. Dette er leksjon 4 av 4. Du kan lese hele leksjonen gratis nedenfor – og deretter øve praktisk i nettleseren med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Den er en del av læringsløpet i C Academy, og fremdriften din synkroniseres mellom nettet og CoddyKit-appen. Kurset i C Academy inneholder totalt 4 leksjoner.

Det vi skal bygge

En ekko-server godtar TCP-tilkoblinger og sender tilbake alle byte en klient sender. Den er nettverksprogrammeringens «hello world».

Vi bygger den med epoll, slik at én tråd kan betjene mange klienter samtidig. Delene er en lyttesocket, epoll-løkken og håndtering av lesing og deretter skriving for hver klient.

Opprette lyttesocketen

Start med socket() for et IPv4 TCP-endepunkt. Trippelen er AF_INET, SOCK_STREAM og protokoll 0.

Dette returnerer en fildeskriptor som vi skal binde, sette i ikke-blokkerende modus og til slutt registrere med epoll. Kontroller -1 ved hvert systemkall.

int listen_fd = socket(AF_INET, SOCK_STREAM, 0);
if (listen_fd == -1) { perror("socket"); exit(1); }

Gjenbruke adressen

Før binding setter De SO_REUSEADDR med setsockopt(). Dette lar serveren starte på nytt og binde seg til den samme porten uten å vente til tilstanden TIME_WAIT er over.

Uten dette mislykkes en rask omstart ofte med EADDRINUSE, noe som er en frustrerende overraskelse under utvikling.

int yes = 1;
setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof yes);

Binde til en port

Fyll ut en struct sockaddr_in med familie, port og adresse. Bruk htons() for porten og INADDR_ANY for å lytte på alle grensesnitt.

Kall deretter bind() for å knytte socketen til adressen. htons konverterer vertsbyterekkefølge til nettverksbyterekkefølge, noe som er nødvendig.

struct sockaddr_in addr = {0};
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(8080);
bind(listen_fd, (struct sockaddr*)&addr, sizeof addr);

Lytte og gå over til ikke-blokkerende modus

Kall listen() for å gjøre socketen passiv og angi en kølengde for ventende tilkoblinger. SOMAXCONN ber om systemets maksimum.

Bytt deretter socketen til ikke-blokkerende modus, slik at accept() aldri stopper hendelsesløkken. Nå er den klar til å registreres med epoll.

listen(listen_fd, SOMAXCONN);
set_nonblocking(listen_fd);

Registrere lytteren

Opprett epoll-forekomsten og legg til lyttesocketen med EPOLLIN. En lesbar hendelse her betyr at en ny klient venter på å bli godtatt.

Vi lagrer fd-en i data.fd, slik at vi kan kjenne igjen lytteren inne i løkken.

int epfd = epoll_create1(0);
struct epoll_event ev = { .events = EPOLLIN, .data.fd = listen_fd };
epoll_ctl(epfd, EPOLL_CTL_ADD, listen_fd, &ev);

Godta en klient

Når lytteren er lesbar, kjører De accept() i en løkke til EAGAIN. Hver nye klientsocket settes i ikke-blokkerende modus og registreres for EPOLLIN.

Fra nå av forteller epoll oss når klienten sender data vi kan sende tilbake som ekko.

int c = accept(listen_fd, NULL, NULL);
if (c != -1) {
    set_nonblocking(c);
    struct epoll_event cev = { .events = EPOLLIN, .data.fd = c };
    epoll_ctl(epfd, EPOLL_CTL_ADD, c, &cev);
}

Ekko-logikken

For en klar klient leser De med recv() inn i et buffer. Hvis De mottar byte, sender De de samme bytene direkte tilbake med send().

Denne enkle les-og-skriv-sekvensen er ekkoet. I produksjon ville De bufret usendte byte, men i en demonstrasjon antar vi at det lille svaret får plass i sendebufferet.

char buf[4096];
ssize_t r = recv(fd, buf, sizeof buf, 0);
if (r > 0) {
    send(fd, buf, r, 0);
}

Oppdage frakobling

En returverdi på 0 fra recv() betyr at klienten har utført en ordnet avslutning. En negativ returverdi med alt annet enn EAGAIN er en reell feil.

I begge tilfeller fjerner De deskriptoren fra epoll og kaller close() på den for å frigjøre ressurser og stoppe flere hendelser.

if (r == 0 || (r < 0 && errno != EAGAIN)) {
    epoll_ctl(epfd, EPOLL_CTL_DEL, fd, NULL);
    close(fd);
}

Den fullstendige løkken

Sett sammen delene: Vent på hendelser, avgjør om deskriptoren er lytteren eller en klient, og handle deretter.

Denne kompakte løkken er en fullt fungerende samtidig ekko-server. Én tråd, mange klienter, ingen tråder per tilkobling.

for (;;) {
    int n = epoll_wait(epfd, events, MAX_EVENTS, -1);
    for (int i = 0; i < n; i++) {
        if (events[i].data.fd == listen_fd) accept_clients();
        else echo_or_close(events[i].data.fd);
    }
}

Testing og neste trinn

Kompiler på Linux og koble til med nc localhost 8080; alt De skriver, kommer tilbake. Åpne flere terminaler for å demonstrere samtidighet.

For å gjøre løsningen mer robust: bufre delvise sendinger, håndter EPOLLOUT, bytt til EPOLLET med full tømming, og håndter EPOLLRDHUP for halvveis lukking.

Hurtigsjekk

Test hvor godt De forstår flyten i ekko-serveren.

Oppsummering

De har bygget en echo-server med epoll: opprettet den, satt SO_REUSEADDR, bundet den, startet lytting og gjort den ikke-blokkerende. Registrer lytte-socketen, godta klienter i en løkke, og send dataene tilbake med recv()/send().

Behandle returverdien 0 som en frakobling, og lukk tilkoblingen på en ryddig måte. Med dette skjelettet kan De bygge videre på en høyytelses nettverksserver med én tråd.

Gratis å komme i gang

Lær deg C med en AI-veileder – gratis

Skriv og kjør ekte kode i nettleseren, få umiddelbar hjelp fra en AI-veileder som er tilgjengelig døgnet rundt, og fortsett der du slapp – på nettet eller i appen.

Kurs
39
Leksjoner
144

Ofte stilte spørsmål

Er leksjonen «En enkel ekkotjener» gratis?

Ja – hele teksten i «En enkel ekkotjener» er gratis å lese her på nettet. For å øve interaktivt med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt, og for å låse opp resten av C Academy-kurset, kan du oppgradere til CoddyKit PRO. Kurset i C Academy inneholder totalt 4 leksjoner.

Hva lærer jeg i «En enkel ekkotjener»?

Betjen mange klienter samtidig. Du øver på C Academy med praktisk kode som du kjører direkte i nettleseren, mens en AI-veileder som er tilgjengelig døgnet rundt, svarer på spørsmålene dine mens du jobber deg gjennom leksjonen.

Trenger jeg erfaring for å begynne med C Academy?

Ingen tidligere erfaring er nødvendig. C Academy på CoddyKit er lagt opp for både nybegynnere og viderekomne, så De kan begynne her eller helt fra start og lære i Deres eget tempo. Dette er leksjon 4 av 4.

Hvor lang tid tar leksjonen «En enkel ekkotjener»?

De fleste CoddyKit-leksjoner tar omtrent 5–10 minutter. Hver leksjon er kort og interaktiv, slik at De gjør jevne fremskritt og kan fortsette akkurat der De slapp – både på nettet og i appen.

Kan jeg skrive og kjøre kode i denne C Academy-leksjonen?

Ja. Alle C Academy-leksjoner har en innebygd kodeeditor, slik at De kan skrive og kjøre ekte kode direkte i nettleseren og få umiddelbar tilbakemelding fra AI – uten lokal konfigurering.

Alle leksjonene i dette kurset

  1. Blokkerende kontra ikke-blokkerende I/O
  2. Sett opp epoll
  3. Hendelsesløkken
  4. En enkel ekkotjener
← Tilbake til C Academy