0Pricing
C Academy · Lekcja

Serwer TCP

Akceptowanie połączeń

Serwer TCP to bezpłatna lekcja C Academy na CoddyKit. To lekcja 2 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej C Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs C Academy zawiera 4 lekcji w sumie.

Budowanie serwera TCP

Serwer TCP oczekuje na klientów i akceptuje ich połączenia. Cykl życia wygląda następująco: utworzenie gniazda, przypisanie go do portu, nasłuchiwanie, a następnie akceptowanie połączeń w pętli.

Krok 1: Utworzenie gniazda

Utwórz gniazdo strumieniowe dla IPv4 TCP. Wynik ujemny oznacza niepowodzenie.

#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;
}

Krok 2: Zezwolenie na ponowne użycie adresu

Domyślnie po zatrzymaniu serwera port pozostaje w stanie TIME_WAIT, uniemożliwiając ponowne uruchomienie. Ustaw SO_REUSEADDR za pomocą setsockopt, aby móc natychmiast ponownie przypisać gniazdo.

#include <sys/socket.h>

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

Krok 3: Przypisanie do portu

bind() przypisuje gniazdo do lokalnego adresu i portu. INADDR_ANY umożliwia nasłuchiwanie na wszystkich interfejsach sieciowych.

#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;
}

Krok 4: Nasłuchiwanie

listen() oznacza gniazdo jako pasywne (gotowe do akceptowania połączeń). Argument backlog określa, ile oczekujących połączeń jądro może umieścić w kolejce.

#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;
}

Krok 5: Akceptowanie połączeń

accept() blokuje działanie do czasu połączenia klienta, a następnie zwraca nowe gniazdo przeznaczone dla tego klienta. Oryginalne gniazdo nadal nasłuchuje.

#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;
}

Dwa gniazda, dwie role

Po wywołaniu accept dostępne są dwa gniazda:

  • Gniazdo nasłuchujące nadal akceptuje nowych klientów
  • Gniazdo połączenia służy do komunikacji z jednym konkretnym klientem

Po zakończeniu obsługi klienta należy zamknąć gniazdo połączenia.

Odczytywanie żądania

Użyj recv, aby odczytać dane klienta do bufora. Wartość 0 oznacza rozłączenie klienta, a -1 — błąd.

#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); }
}

Wysyłanie odpowiedzi

Odpowiedz za pomocą send. W przypadku dużych danych wykonuj pętlę, aż wszystkie bajty zostaną wysłane, ponieważ pojedyncze wywołanie może zapisać tylko część bufora.

#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;
    }
}

Pętla akceptowania

Prosty serwer iteracyjny akceptuje jednego klienta, obsługuje go, zamyka połączenie, a następnie wraca do pętli i akceptuje kolejnego. Obsługuje klientów pojedynczo.

#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 */
    }
}

Kontrolowane zamykanie

Po zatrzymaniu serwera zamknij gniazdo nasłuchujące i obsłuż SIGINT, aby prawidłowo przerwać pętlę. Zawsze zamykaj deskryptory, aby zwalniać zasoby jądra.

Szybkie sprawdzenie

Sprawdź swoją wiedzę na temat serwerów TCP.

Podsumowanie

Zbudowali Państwo serwer TCP krok po kroku.

  • socket, następnie SO_REUSEADDR, bind, listen i accept
  • accept zwraca nowe gniazdo dla każdego klienta
  • recv/send służą do komunikacji, a następnie połączenie należy zamknąć
  • Używaj pętli do obsługi klientów i sprawdzaj każdą wartość zwracaną

Często zadawane pytania

Czy lekcja „Serwer TCP” jest bezpłatna?

Tak — pełny tekst „Serwer TCP” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu C Academy, przejdź na CoddyKit PRO. Kurs C Academy zawiera 4 lekcji w sumie.

Co nauczysz się w „Serwer TCP”?

Akceptowanie połączeń Ćwiczysz C Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć C Academy?

Nie wymagamy żadnego doświadczenia. C Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 2 z 4.

Ile czasu zajmuje lekcja „Serwer TCP”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji C Academy?

Tak. Każda lekcja C Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Przegląd gniazd
  2. Serwer TCP
  3. Klient TCP
  4. Obsługa wielu klientów
← Powrót do C Academy