11 Stimmen

Tipps für die Entwicklung eines Webservers

Nachdem ich hier etwas gesucht habe, habe ich so gut wie keine Fragen zur Entwicklung eines Webservers gefunden.

Ich werde dies hauptsächlich aus zwei Gründen tun. Als Nebenprojekt und um mehr über die Entwicklung eines Serverprogramms zu lernen. Daraus wird keine brauchbare Anwendung werden, sondern eher ein Lernwerkzeug

Die Fragen sind also einfach.

  • Haben Sie einen Webserver entwickelt? (egal in welcher Sprache)
  • Welche Probleme gibt es und welche guten Tipps können Sie geben?

Links zu hilfreichen Websites sind willkommen, aber verlinken Sie nicht auf ein funktionierendes Open-Source-Projekt, da es hier um den Lernprozess geht.

20voto

Charlie Martin Punkte 106684

Ein Webserver ist zu Beginn ein sehr einfaches Stück Code:

  • einen TCP/IP-Socket an Port 80 öffnen
  • solange sie nicht beendet ist
    • auf Verbindungen an diesem Socket warten
    • wenn Ihnen jemand HTTP-Header sendet
      • den Pfad zur Datei finden
      • Kopieren der Datei in den Socket

Die Gliederung des Codes ist also einfach.

Nun haben Sie einige komplexe Aufgaben zu bewältigen:

  • In der einfachsten Version des Codes können alle anderen Browser keine Verbindung herstellen, während Sie mit einem Browser kommunizieren. Sie müssen sich etwas einfallen lassen, wie Sie mit mehreren Verbindungen umgehen können.
  • Es ist oft praktisch, mehr als nur eine statische Datei versenden zu können (obwohl die ersten HTTP-Server genau das taten), so dass man in der Lage sein muss, andere Programme auszuführen.

Auch die Möglichkeit, mehrere Verbindungen herzustellen, ist relativ einfach zu handhaben, da es eine Reihe von Auswahlmöglichkeiten gibt.

  • Die einfachste Version (und das ist auch die Art und Weise, wie es ursprünglich gemacht wurde) besteht darin, dass der Code, der Port 80 abhört, einen speziellen Socket für diese Verbindung einrichtet und dann eine Kopie von sich selbst forkt, um diese eine Verbindung zu behandeln. Dieser Prozess läuft, bis der Socket geschlossen wird, und wird dann beendet. Das ist jedoch relativ teuer: Ein Fork dauert in der Regel mehrere zehn Millisekunden, so dass die Ausführungsgeschwindigkeit begrenzt ist.
  • Die zweite Möglichkeit besteht darin, einen leichtgewichtigen Prozess zu erstellen - auch bekannt als Gewinde - um die Anfrage zu bearbeiten.

Auch das Ausführen eines Programms ist eigentlich recht einfach. Im Allgemeinen definieren Sie einen speziellen Pfad zu einem CGI-Verzeichnis; eine URL, die einen Pfad durch dieses Verzeichnis hat, interpretiert dann den Pfadnamen als den Pfad zu einem Programm. Der Server erstellt dann mit fork/exec einen Unterprozess, wobei STDOUT mit dem Socket verbunden wird. Das Programm wird dann ausgeführt und sendet die Ausgabe an STDOUT, die dann an den Client-Browser weitergeleitet wird.

Dies ist das Grundmuster; alles andere, was ein Webserver tut, ist nur das Hinzufügen von Schnörkeln und zusätzlichen Funktionen zu diesem Grundmuster.

Hier sind einige andere Quellen für Beispielcode:


Es tut so gut wie nichts von dem, was Sie wirklich wollten, aber für einfach es ist schwer zu übertreffen diese de http://www.commandlinefu.com :

$ python -m SimpleHTTPServer

0 Stimmen

Ich habe sogar schon eine noch einfachere Version in Python, ich bin erstaunt, wie einfach es war. Es sendet nur einen statischen Header und Inhalt.

0 Stimmen

Sehr schöne Ergänzung zur Antwort.

10voto

rein Punkte 31987

Erstens: Bitte lassen Sie dies nicht zu einem brauchbaren Projekt werden - die Sicherheit von Webservern zu gewährleisten, ist wirklich schwierig.

Ok, hier sind einige Dinge, die Sie beachten sollten:

  1. Der Thread, der die Verbindungen annimmt, muss seine Arbeit an Hintergrund-Threads so schnell wie möglich möglich.
  2. Sie können kein Thema haben für jede einzelne Verbindung haben - bei großen Mengen werden Sie Ihr Thread-Limit.
  3. Verwenden Sie eine Art von Worker-Thread-Pool zur Bearbeitung Ihrer Anfragen.
  4. Stellen Sie sicher, dass Sie schrubben die URL, wenn Sie eine HTTP GET Anfrage erhalten. Ich könnte also nicht etwas tun wie http://localhost/../../Users/blah/ um Zugang zu einer höheren Ebene zu erhalten.
  5. Stellen Sie sicher, dass Sie immer die entsprechenden Inhalts- und Mime-Typen.

Viel Glück - das ist ein anstrengender Job.

0 Stimmen

Nachdem ich im Internet als Website-Entwickler gearbeitet habe, weiß ich gut über die Sicherheit der Sache Bescheid :) Trotzdem eine gute Antwort.

0 Stimmen

Mit dem Wissen um die Risiken, die mit der Veröffentlichung von ausführbarem Code im Internet verbunden sind, sind Sie den meisten Entwicklern weit voraus :)

2voto

Will Hartung Punkte 110997

Die Vernetzung und alles andere ist ziemlich normal, also machen Sie sich darüber nicht so viele Gedanken. (Es gibt mehrere "Instant", Beispiel-Netzwerk-Server in fast jeder Sprache.)

Konzentrieren Sie sich stattdessen auf die tatsächliche Implementierung der HTTP-Spezifikation. Sie werden erstaunt sein, a) was Sie nicht wissen und b) wie viele Dinge, die angeblich HTTP-konform sind, es in Wirklichkeit nicht sind, aber gut vorgetäuscht werden.

Dann werden Sie sich wundern, dass das Internet überhaupt funktioniert.

Wenn Sie mit HTTP fertig sind, können Sie versuchen, IMAP zu implementieren.

1voto

Serapth Punkte 7022

Ich habe vor ein paar Jahren einen leichten Webserver in Python geschrieben, auch als Lernprojekt.

Der einfachste Ratschlag, den ich geben kann, vor allem als Lernprojekt, ist, einen funktionierenden Kern zu entwickeln und dann iterativ darauf aufzubauen. Fangen Sie nicht gleich mit dem Mond an, sondern fangen Sie ganz klein an, fügen Sie dann Funktionen hinzu, verfeinern Sie sie und machen Sie weiter. Ich würde empfehlen, ein Werkzeug zu verwenden, das zum Experimentieren anregt, wie z. B. Python, wo man buchstäblich gleichzeitig Code tippen und testen kann.

1voto

Alex Gartrell Punkte 2454

In dem Kurs, den ich geleitet habe, gab es eine Bevollmächtigungsaufgabe, so dass ich hier ein wenig Licht ins Dunkel bringen kann, denke ich.

Sie werden also eine Menge Header-Änderungen vornehmen müssen, nur um sich das Leben leichter zu machen. HTTP/1.0 ist nämlich viel einfacher zu handhaben als HTTP/1.1. Sie wollen sich nicht mit der Verwaltung von Timeouts und Keep-Alives und ähnlichem beschäftigen. Eine Verbindung pro Transaktion ist am einfachsten.

Sie werden eine Menge Parsing machen müssen. Parsing ist in C schwierig. Ich würde Ihnen raten, eine Funktion zu schreiben, die etwa so aussieht

int readline(char *buff, int maxLen) {
    while((c = readNextCharFromSocket(&s)) && c != '\n' && i < maxLen)
      buff[i++] = c;
    return i;
}

und eine Zeile nach der anderen zu bearbeiten, nur weil es am einfachsten ist, die vorhandenen C-String-Funktionen in einer Zeile zu verwenden. Denken Sie auch daran, dass die Zeilen \r\n getrennt und die Kopfzeilen werden mit einem \r\n\r\n.

Das Hauptproblem wird das Parsen sein, solange Sie Dateien lesen können, wird alles andere wie erwartet funktionieren.

Für die Fehlersuche werden Sie wahrscheinlich Header ausdrucken wollen, die herumgereicht werden, um sie auf ihre Tauglichkeit zu prüfen, wenn etwas nicht funktioniert.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X