typestar

tcp_echo.c en C

Un servidor de eco de un solo hilo: bind, listen, accept, eco, repetir.

#include <arpa/inet.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>

#define PORT 9099
#define BACKLOG 4

static int serve_client(int client) {
    char buffer[512];
    ssize_t n;

    while ((n = read(client, buffer, sizeof buffer)) > 0) {
        ssize_t written = 0;
        while (written < n) {
            ssize_t w = write(client, buffer + written, (size_t) (n - written));
            if (w <= 0) {
                return 0;
            }
            written += w;
        }
    }
    return n == 0;
}

int main(void) {
    int listener = socket(AF_INET, SOCK_STREAM, 0);
    if (listener < 0) {
        perror("socket");
        return 1;
    }

    int reuse = 1;
    setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof reuse);

    struct sockaddr_in addr;
    memset(&addr, 0, sizeof addr);
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
    addr.sin_port = htons(PORT);

    if (bind(listener, (struct sockaddr *) &addr, sizeof addr) != 0) {
        perror("bind");
        close(listener);
        return 1;
    }
    if (listen(listener, BACKLOG) != 0) {
        perror("listen");
        close(listener);
        return 1;
    }

    printf("echoing on 127.0.0.1:%d\n", PORT);

    for (int served = 0; served < 3; served++) {
        struct sockaddr_in peer;
        socklen_t peer_len = sizeof peer;
        int client = accept(listener, (struct sockaddr *) &peer, &peer_len);
        if (client < 0) {
            perror("accept");
            continue;
        }

        char who[INET_ADDRSTRLEN] = "?";
        inet_ntop(AF_INET, &peer.sin_addr, who, sizeof who);
        printf("client from %s\n", who);

        if (!serve_client(client)) {
            fprintf(stderr, "client dropped\n");
        }
        close(client);
    }

    close(listener);
    return 0;
}

Cómo funciona

  1. SO_REUSEADDR deja religar el puerto de inmediato tras un reinicio.
  2. El bucle de accept atiende un cliente a la vez hasta terminar.
  3. Cada ruta de error cierra lo que abrió y reporta por qué.

Palabras clave y builtins usados aquí

El intento, en números

Líneas
77
Caracteres a escribir
1502
Tokens
420
Ritmo de tres estrellas
110 tpm

Al ritmo de tres estrellas de 110 tokens por minuto, este intento toma unos 229 segundos.

Escribe este fragmento

Paso 1 de 1 en Bis; paso 14 de 14 en Programación de sistemas.

← Anterior