C Academy · Oppitunti

TCP-palvelin

Hyväksy yhteyksiä.

Oppitunti 2/413 vaihetta

TCP-palvelin on ilmainen C Academy-oppitunti CoddyKitissä. Tämä on oppitunti 2/4. Voit lukea koko oppitunnin alta ilmaiseksi ja harjoitella sen jälkeen käytännössä selaimessa sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla. Oppitunti kuuluu C Academy-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. C Academy-kurssilla on yhteensä 4 oppituntia.

TCP-palvelimen rakentaminen

TCP-palvelin odottaa asiakkaita ja hyväksyy niiden yhteydet. Elinkaari on seuraava: luodaan socket, sidotaan se porttiin, aloitetaan kuuntelu ja hyväksytään yhteyksiä silmukassa.

Vaihe 1: Luo socket

Luokaa IPv4-TCP:tä varten stream-tyyppinen socket. Negatiivinen tulos tarkoittaa virhettä.

#include <sys/socket.h>
#include <stdio.h>

int make_server_socket(void) {
    int fd = socket(AF_INET, SOCK_STREAM, 0);
    if (fd < 0) { perror("socket"); }
    return fd;
}

Vaihe 2: Salli osoitteen uudelleenkäyttö

Oletusarvoisesti portti jää palvelimen pysäyttämisen jälkeen TIME_WAIT-tilaan, mikä estää uudelleenkäynnistyksen. Asettakaa SO_REUSEADDR funktion setsockopt avulla, jotta voitte sitoa portin uudelleen heti.

#include <sys/socket.h>

void allow_reuse(int fd) {
    int yes = 1;
    setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof yes);
}

Vaihe 3: Sido socket porttiin

bind() liittää socketin paikalliseen osoitteeseen ja porttiin. INADDR_ANY kuuntelee kaikissa verkkoliitännöissä.

#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>

int bind_port(int fd, unsigned short port) {
    struct sockaddr_in addr = {0};
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = INADDR_ANY;
    addr.sin_port = htons(port);
    if (bind(fd, (struct sockaddr *)&addr, sizeof addr) < 0) {
        perror("bind"); return -1;
    }
    return 0;
}

Vaihe 4: Aloita kuuntelu

listen() merkitsee socketin passiiviseksi eli valmiiksi hyväksymään yhteyksiä. backlog-argumentti määrittää, kuinka monta odottavaa yhteyttä ydin voi jonottaa.

#include <sys/socket.h>
#include <stdio.h>

int start_listen(int fd) {
    if (listen(fd, 16) < 0) { /* backlog of 16 */
        perror("listen"); return -1;
    }
    return 0;
}

Vaihe 5: Hyväksy yhteydet

accept() estää suorituksen, kunnes asiakas yhdistää, ja palauttaa sitten uuden socketin kyseistä asiakasta varten. Alkuperäinen socket jatkaa kuuntelua.

#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>

int accept_one(int listen_fd) {
    struct sockaddr_in cli;
    socklen_t len = sizeof cli;
    int conn = accept(listen_fd, (struct sockaddr *)&cli, &len);
    if (conn < 0) perror("accept");
    return conn;
}

Kaksi socketia, kaksi roolia

accept-kutsun jälkeen käytettävissä on kaksi socketia:

  • Kuunteleva socket hyväksyy uusia asiakkaita
  • Yhteyssocket viestii yhden tietyn asiakkaan kanssa

Sulkeakaa yhteyssocket, kun kyseisen asiakkaan käsittely on valmis.

Pyynnön lukeminen

Käyttäkää funktiota recv lukeaksenne asiakkaan tiedot puskuriin. Paluuarvo 0 tarkoittaa, että asiakas katkaisi yhteyden; -1 tarkoittaa virhettä.

#include <sys/socket.h>
#include <stdio.h>

void handle(int conn) {
    char buf[256];
    ssize_t n = recv(conn, buf, sizeof buf - 1, 0);
    if (n > 0) { buf[n] = 0; printf("got: %s\n", buf); }
}

Vastauksen lähettäminen

Vastatkaa funktiolla send. Suurten tietomäärien tapauksessa lähettäkää kaikki tavut silmukassa, koska yksi kutsu voi kirjoittaa vain osan puskurista.

#include <sys/socket.h>
#include <string.h>

void reply(int conn) {
    const char *msg = "hello from server\n";
    size_t left = strlen(msg);
    const char *p = msg;
    while (left > 0) {
        ssize_t n = send(conn, p, left, 0);
        if (n <= 0) break;
        p += n; left -= (size_t)n;
    }
}

Hyväksymissilmukka

Yksinkertainen iteratiivinen palvelin hyväksyy yhden asiakkaan, palvelee sitä, sulkee yhteyden ja palaa sitten silmukan alkuun hyväksymään seuraavan. Se käsittelee asiakkaita yksi kerrallaan.

#include <unistd.h>

void serve_loop(int listen_fd, int (*accept_one)(int), void (*handle)(int)) {
    for (;;) {
        int conn = accept_one(listen_fd);
        if (conn < 0) continue;
        handle(conn);
        close(conn); /* done with this client */
    }
}

Hallittu sammutus

Sulkeakaa kuunteleva socket palvelimen pysähtyessä ja käsitelkää SIGINT, jotta silmukasta voidaan poistua hallitusti. Sulkekaa aina kuvaajat ytimen resurssien vapauttamiseksi.

Pikatarkistus

Testatkaa, miten hyvin ymmärrätte TCP-palvelimia.

Kertaus

Rakensitte TCP-palvelimen vaihe vaiheelta.

  • socket, sitten SO_REUSEADDR, sitten bind, listen ja accept
  • accept palauttaa uuden asiakaskohtaisen socketin
  • Viestikää funktioilla recv/send ja sulkekaa yhteys sen jälkeen
  • Käsitelkää asiakkaat silmukassa ja tarkistakaa jokainen paluuarvo
Aloita maksutta

Opi C tekoälytuutorin avulla — ilmaiseksi

Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.

Kurssit
39
Oppitunnit
144

Usein kysytyt kysymykset

Onko oppitunti ”TCP-palvelin” ilmainen?

Kyllä – oppitunnin ”TCP-palvelin” koko tekstin voi lukea täällä verkossa ilmaiseksi. Jos haluat harjoitella interaktiivisesti sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla sekä avata koko C Academy-kurssin, päivitä CoddyKit PROhon. C Academy-kurssilla on yhteensä 4 oppituntia.

Mitä opin oppitunnilla ”TCP-palvelin”?

Hyväksy yhteyksiä. Harjoittelet C Academy-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.

Tarvitsenko kokemusta aloittaakseni C Academy-opiskelun?

Aiempi kokemus ei ole tarpeen. CoddyKitin C Academy-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 2/4.

Kuinka kauan ”TCP-palvelin”-oppitunnin suorittaminen kestää?

Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.

Voinko kirjoittaa ja suorittaa koodia tällä C Academy-oppitunnilla?

Kyllä. Jokainen C Academy-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.

Kaikki tämän kurssin oppitunnit

  1. Pistokkeiden yleiskatsaus
  2. TCP-palvelin
  3. TCP-asiakas
  4. Useiden asiakkaiden käsittely
← Takaisin: C Academy