Preise

Schnellstart

Quelldateien

Diese Seite wurde aus den folgenden Quelldateien erstellt:

Kompilierung und Vorbereitung

Tinyhttpd ist ein minimalistischer HTTP-Server, der ursprünglich für Sparc Solaris 2.6 entwickelt wurde. Für die Kompilierung unter Linux sind spezifische Anpassungen im Quellcode erforderlich.

Build-Konfiguration

Das Projekt verwendet ein einfaches Makefile, das zwei Hauptziele definiert: den Server (httpd) und einen Testclient (client). Die Kompilierung erfolgt mit GCC und bindet die pthread-Bibliothek ein (Makefile:1-9).

bash
1# Kompilierung starten
2make all

Das Makefile definiert folgende Build-Regeln:

  • httpd: Kompiliert httpd.c mit Debug-Symbolen (-g) und aktivierten Warnungen (-W -Wall)
  • client: Kompiliert simpleclient.c zu einer ausführbaren Testanwendung
  • clean: Entfernt die generierte httpd-Binary

Linux-spezifische Anpassungen

Der Quellcode enthält Kommentare zur Linux-Portierung. Für die Kompilierung unter Linux müssen folgende Änderungen vorgenommen werden (httpd.c:7-14):

  1. Die Zeile #include <pthread.h> auskommentieren
  2. Die Variable newthread auskommentieren
  3. Die beiden pthread_create()-Aufrufe auskommentieren
  4. Den Aufruf von accept_request() einkommentieren
  5. -lsocket aus dem Makefile entfernen

Die README-Datei bestätigt diese Anpassungen und bietet eine detaillierte Anleitung für die Linux-Kompilierung (README.md:5-14).

Abhängigkeiten

Für CGI-Tests muss das System über Perl verfügen. Die README spezifiziert, dass sowohl Perl als auch das Modul perl-cgi installiert sein müssen (README.md:1-3).

bash
1# Debian/Ubuntu
2sudo apt-get install perl libcgi-pm-perl
3
4# CentOS/RHEL
5sudo yum install perl perl-CGI

Server-Initialisierung

Die Server-Initialisierung erfolgt über die Funktion startup(), die einen TCP-Socket erstellt, diesen an einen Port bindet und auf eingehende Verbindungen wartet.

Socket-Erstellung und Konfiguration

Die startup()-Funktion implementiert die vollständige Server-Initialisierung (httpd.c:429-458):

c
1int startup(u_short *port)
2{
3    int httpd = 0;
4    int on = 1;
5    struct sockaddr_in name;
6
7    httpd = socket(PF_INET, SOCK_STREAM, 0);
8    // ... Fehlerbehandlung ...
9    memset(&name, 0, sizeof(name));
10    name.sin_family = AF_INET;
11    name.sin_port = htons(*port);
12    name.sin_addr.s_addr = htonl(INADDR_ANY);
13    // ... bind() und listen() ...
14}

Die Funktion führt folgende Schritte aus:

  1. Erstellung eines TCP-Sockets mit socket(PF_INET, SOCK_STREAM, 0)
  2. Setzen der SO_REUSEADDR-Socket-Option zur Wiederverwendung lokaler Adressen
  3. Binden des Sockets an alle verfügbaren Netzwerkschnittstellen (INADDR_ANY)
  4. Starten des Listening mit einer Backlog-Queue von 5 Verbindungen

Dynamische Portzuweisung

Wenn der Port-Parameter mit dem Wert 0 übergeben wird, weist das System dynamisch einen freien Port zu. Die Funktion ermittelt den tatsächlich zugewiesenen Port über getsockname() und aktualisiert die Port-Variable (httpd.c:448-453).

Die README beschreibt den Server-Start wie folgt: Der Server startet und bindet den HTTP-Dienst an einen angegebenen Port oder wählt zufällig einen Port aus (README.md:35-36).

Anfrageverarbeitung und Workflow

Die Anfrageverarbeitung folgt einem klaren Workflow, der in der README dokumentiert ist und durch die Funktionen in httpd.c implementiert wird.

HTTP-Request-Parsing

Beim Empfang einer HTTP-Anfrage extrahiert der Server zunächst die HTTP-Methode (GET oder POST) und die URL. Bei GET-Anfragen mit Parametern zeigt der query_string-Zeiger auf den Teil nach dem Fragezeichen (README.md:37-40).

Die URL wird in das path-Array formatiert, wobei der Pfad relativ zum htdocs-Verzeichnis interpretiert wird. Endet die URL mit einem Schrägstrich oder verweist auf ein Verzeichnis, wird automatisch index.html angehängt.

CGI-Entscheidung und Datei-Serving

Der Server entscheidet basierend auf folgenden Kriterien, ob eine Anfrage als CGI behandelt wird:

  • Die Anfrage verwendet die POST-Methode
  • Die GET-Anfrage enthält Query-Parameter (Fragezeichen in der URL)
  • Die Zieldatei ist als ausführbar markiert (S_IXUSR, S_IXGRP oder S_IXOTH)

Für statische Dateien ruft der Server die Funktion serve_file() auf (httpd.c:400-419). Diese Funktion:

  1. Liest und verwirft die HTTP-Header der Anfrage
  2. Öffnet die angeforderte Datei
  3. Sendet HTTP-Header an den Client
  4. Überträgt den Dateiinhalt über den Socket
正在加载图表渲染器...

Verzeichnisbehandlung

Wenn der angeforderte Pfad ein Verzeichnis ist, wird automatisch index.html an den Pfad angehängt. Dies geschieht in der accept_request()-Funktion, nachdem stat() bestätigt hat, dass der Pfad existiert (httpd.c:121-122).

Testen und Abhängigkeiten

CGI-Testanforderungen

Für die Ausführung der mitgelieferten CGI-Skripte sind zusätzliche Abhängigkeiten erforderlich. Die README spezifiziert, dass Perl und das Modul perl-cgi installiert sein müssen (README.md:1-3).

Die CGI-Skripte befinden sich im Verzeichnis htdocs/ und umfassen:

  • check.cgi - Ein Testskript für CGI-Funktionalität
  • color.cgi - Ein interaktives Farbskript (der ursprüngliche Autor empfiehlt, "chartreuse" als Eingabe zu testen)

Client-Kommunikationstest

Das Projekt enthält einen einfachen Testclient (simpleclient.c), der eine Verbindung zum Server auf Port 9734 herstellt (simpleclient.c:8-33).

c
1// simpleclient.c - Verbindung zum lokalen Server
2address.sin_addr.s_addr = inet_addr("127.0.0.1");
3address.sin_port = htons(9734);

Der Client sendet ein einzelnes Zeichen an den Server und liest die Antwort. Dies dient zur grundlegenden Überprüfung der Socket-Kommunikation.

Manueller Test mit curl

Nach erfolgreicher Kompilierung und Start des Servers kann die Funktionalität mit curl getestet werden:

bash
1# Statische Datei abrufen
2curl http://localhost:<PORT>/index.html
3
4# CGI-Skript testen
5curl "http://localhost:<PORT>/color.cgi?color=chartreuse"

Hinweis: Der tatsächliche Port muss der Serverausgabe entnommen werden oder vor der Kompilierung festgelegt werden (需要确认: Der Standardport ist nicht explizit im Quellcode definiert; die Portnummer wird beim Serverstart angezeigt).

Installation und Start

Empfohlene Installationssequenz

bash
1# 1. Repository klonen
2git clone https://github.com/EZLippi/Tinyhttpd.git
3cd Tinyhttpd
4
5# 2. Abhängigkeiten installieren (für CGI-Tests)
6sudo apt-get install perl libcgi-pm-perl
7
8# 3. Linux-Anpassungen vornehmen (manuell in httpd.c)
9#    - Zeile 25: #include <pthread.h> auskommentieren
10#    - pthread_create-Aufrufe auskommentieren
11#    - accept_request() Aufruf einkommentieren
12
13# 4. Kompilieren
14make all
15
16# 5. Server starten
17./httpd

Kompilierungsoptionen

MethodeBefehlBeschreibung
Vollständigmake allKompiliert Server und Client
Nur Servermake httpdKompiliert nur den HTTP-Server
Nur Clientmake clientKompiliert nur den Testclient
Bereinigungmake cleanEntfernt generierte Binärdateien

Laufzeitverifikation

Erfolgreicher Server-Start

Nach dem Start gibt der Server den verwendeten Port auf der Standardausgabe aus. Die README beschreibt, dass der Server bei der Initialisierung einen Port bindet - entweder den angegebenen oder einen dynamisch zugewiesenen (README.md:35-36).

Erwartete Ausgabe (需要确认: Das genaue Ausgabeformat ist im Quellcode nicht explizit dokumentiert):

httpd running on port <PORT>

Funktionsprüfung

  1. Statische Dateien: Aufruf von http://localhost:<PORT>/ sollte die index.html ausliefern
  2. CGI-Funktionalität: Aufruf von http://localhost:<PORT>/color.cgi sollte das CGI-Skript ausführen
  3. Fehlerbehandlung: Aufruf einer nicht existierenden Datei sollte einen 404-Fehler zurückgeben

Test mit dem mitgelieferten Client

bash
1# Client kompilieren und ausführen
2make client
3./client

Der Client verbindet sich mit 127.0.0.1:9734 und erwartet eine Antwort vom Server (simpleclient.c:18-19).

Hinweis: Der Client verwendet einen fest codierten Port 9734. Wenn der Server auf einem anderen Port läuft, schlägt die Verbindung fehl (需要确认: Eine Konfigurationsmöglichkeit für den Client-Port ist nicht im Quellcode vorhanden).

Häufige Probleme und Lösungen

Problem 1: Kompilierungsfehler unter Linux

Symptom: Fehlermeldungen bezüglich pthread.h oder -lsocket während der Kompilierung.

Ursache: Der Code wurde ursprünglich für Solaris entwickelt und verwendet pthreads sowie die Socket-Bibliothek.

Lösung: Die in der README dokumentierten Anpassungen müssen vollständig umgesetzt werden (README.md:5-14):

  • Alle pthread-relevanten Zeilen auskommentieren
  • -lsocket aus dem Makefile entfernen
  • Den sequentiellen accept_request()-Aufruf aktivieren

Problem 2: CGI-Skripte werden nicht ausgeführt

Symptom: CGI-Skripte werden als Text angezeigt statt ausgeführt zu werden.

Ursache: Fehlende Perl-Installation oder das Modul perl-cgi ist nicht installiert.

Lösung: Installation der erforderlichen Abhängigkeiten (README.md:1-3):

bash
1sudo apt-get install perl libcgi-pm-perl

Zusätzlich muss sichergestellt werden, dass die CGI-Dateien ausführbare Berechtigungen haben:

bash
1chmod +x htdocs/*.cgi

Problem 3: Port bereits belegt

Symptom: Server startet nicht mit der Meldung "bind: Address already in use".

Ursache: Der angeforderte Port wird bereits von einem anderen Prozess verwendet.

Lösung:

  • Verwendung von Port 0 für dynamische Zuweisung (empfohlen)
  • Oder: Identifizieren und Beenden des Prozesses, der den Port belegt

Die SO_REUSEADDR-Option ist bereits im Code implementiert (httpd.c:442-445), was schnelle Neustarts ermöglicht.

Problem 4: Client-Verbindungsfehler

Symptom: Der Testclient meldet "oops: client1" und bricht ab.

Ursache: Der Server läuft nicht auf Port 9734 oder ist nicht gestartet.

Lösung:

  1. Sicherstellen, dass der Server läuft
  2. Den vom Server verwendeten Port prüfen
  3. Bei Bedarf den Client-Quellcode anpassen (simpleclient.c:19) oder den Server mit festem Port starten

Nächste Schritte

Nach erfolgreicher Installation und Verifikation können folgende Aspekte vertieft werden:

Quellcode-Analyse

Die README empfiehlt eine bestimmte Lesereihenfolge für das Verständnis des Codes: mainstartupaccept_requestexecute_cgi (README.md:31). Diese Reihenfolge folgt dem natürlichen Programmfluss und ermöglicht ein schrittuelles Verständnis der Server-Architektur.

Funktionsübersicht

Die README enthält eine detaillierte Beschreibung aller Hauptfunktionen (README.md:16-28):

  • accept_request: Verarbeitung eingehender HTTP-Anfragen
  • execute_cgi: Ausführung von CGI-Programmen
  • serve_file: Auslieferung statischer Dateien
  • startup: Server-Initialisierung

Erweiterte Konfiguration

Für Produktionszwecke sind folgende Anpassungen empfehlenswert (需要确认: Diese Vorschläge basieren auf allgemeinen Best Practices und sind nicht explizit im Repository dokumentiert):

  • Implementierung von Logging-Mechanismen
  • Hinzufügen von Konfigurationsdatei-Unterstützung
  • Integration von HTTPS-Unterstützung
  • Implementierung von Request-Throttling