Wie das Internet funktioniert
Kurz gesagt: Das Internet ist ein Netz aus Netzen: Eine Seite reist in Paketen zwischen IP-Adressen, DNS macht aus dem Namen der Website eine Adresse, und Browser und Server sprechen über HTTP miteinander.
Problem
Zwischen Enter und der Seite
Du tippst shop.example.bg in den Browser, drückst Enter, und eine halbe Sekunde später siehst du den Katalog mit Kaffee und Tee. Die Seite liegt auf einem Computer in einer anderen Stadt, vielleicht in einem anderen Land. Wie findet der Browser sie? Woher weiß er, dass du den Katalog willst und nicht den Warenkorb? Was genau sagen sich die beiden Programme?
In der nächsten Lektion schreibst du einen Server, der dem Browser antwortet. Dafür musst du die Sprache kennen, in der die beiden sprechen.
Die Idee
Pakete, Router und IP-Adressen
Das Internet ist ein Netz aus Netzen: dein Router zu Hause, das Netz deines Anbieters, die Netze von Ländern und Rechenzentren, alle miteinander verbunden.
- Daten reisen nicht in einem Stück. Sie werden in Pakete aufgeteilt, kleine Teile von etwa 1500 Bytes. Jedes Paket trägt die Adresse, für die es bestimmt ist.
- Ein Router ist ein Gerät, das ein Paket empfängt und an das nächste Netz auf dem Weg weiterschickt. Ein Paket geht durch 10 bis 20 Router, und jeder bringt es seinem Ziel näher.
- Eine IP-Adresse ist die Nummer eines Geräts im Netz, zum Beispiel
93.184.215.14. Dein eigener Computer heißt immer auchlocalhost(127.0.0.1). - Ein Port ist eine Zahl von 0 bis 65 535 für ein Programm auf diesem Computer. Die IP-Adresse ist das Haus, der Port die Wohnung. Webserver lauschen meist auf 80 (HTTP) und 443 (HTTPS).
Die Regeln, wie gesprochen wird, heißen Protokolle. IP liefert einzelne Pakete, verspricht aber nicht, dass sie ankommen. TCP baut auf IP auf: Es stellt eine Verbindung zwischen zwei Programmen her, nummeriert die Pakete, bringt sie in die richtige Reihenfolge und schickt verlorene noch einmal. Deshalb heißen die beiden zusammen TCP/IP.
Genauer, für Neugierige
- Adressen wie
93.184.215.14sind IPv4: vier Zahlen von 0 bis 255, etwa 4 Milliarden Adressen. Das reicht nicht, also gibt es auch IPv6:2606:2800:21f:cb07:6820:80da:af6b:8b2c. - Neben TCP gibt es UDP: keine Verbindung und kein erneutes Senden von Verlorenem, dafür schneller. Es wird für Sprache und Video live und für Spiele verwendet. Das Web läuft über TCP.
- Die beiden Enden einer TCP-Verbindung heißen Sockets: eine Adresse und ein Port auf jeder Seite. Der Port des Browsers wird automatisch aus den freien gewählt.
Die Idee
Ein Name statt einer Zahl: DNS
Menschen merken sich Namen, Computer suchen nach IP-Adresse. Eine Domain ist der menschliche Name einer Website: shop.example.bg. DNS (Domain Name System) macht aus dem Namen eine Adresse:
- Der Browser fragt den DNS-Server des Anbieters: „Wie lautet die Adresse von
shop.example.bg?“ - Wenn er es nicht weiß, fragt er die Kette entlang: den Server für
.bg, dann den Server vonexample.bg. - Die Antwort ist eine IP-Adresse. Der Browser merkt sie sich eine Weile und fragt beim nächsten Mal nicht.
Erst dann verbindet sich der Browser über TCP mit dieser Adresse, auf Port 443.
Die ganze Reise einer Seite, mit dem Teil der Adresse, den jeder Schritt verwendet:
Uri address = new Uri("https://shop.example.bg/products?category=coffee");Console.WriteLine("1. DNS: Wie lautet die Adresse von " + address.Host + "?");Console.WriteLine("2. TCP: Verbindung zu Port " + address.Port);Console.WriteLine("3. HTTP: GET " + address.PathAndQuery);Schritt für Schritt, in Worten
- Die Adresse sagt alles Nötige: welches Protokoll, welcher Computer und welche Ressource.
- Zuerst der Name: Der Browser fragt DNS nach der IP-Adresse von shop.example.bg.
- DNS antwortet mit einer IP-Adresse, zum Beispiel 93.184.215.14. Der Browser merkt sie sich.
- Eine TCP-Verbindung zu dieser Adresse. Der Port steht nicht in der Adresse, also ist es 443, der für https.
- Über die Verbindung geht eine HTTP-Anfrage: die Methode GET und der Pfad /products?category=coffee.
- Der Server antwortet: Status 200 OK und HTML. Der Browser zeichnet die Seite.
- Drei Schritte: ein Name wird zur Adresse (DNS), eine Verbindung (TCP), eine Anfrage und eine Antwort (HTTP).
Hosting ist der Computer, auf dem die Website lebt: ein Server in einem Rechenzentrum, immer an und verbunden. Die Domain zeigt auf das Hosting: DNS sagt „shop.example.bg ist unter dieser IP-Adresse“.
Genauer, für Neugierige
- Eine Domain registrierst du gegen eine jährliche Gebühr bei einem Registrar: einer Firma, die für diese Endung (
.bg,.com,.eu) zugelassen ist. Die Registrierung gilt für eine feste Zeit, meist ein Jahr, und du verlängerst sie. Wenn du sie nicht verlängerst, wird der Name frei, und jeder kann ihn nehmen. Eine gute Domain ist kurz, leicht zu merken und sagt, wofür die Website da ist. - Es gibt mehrere Arten von Hosting. Shared: viele Websites auf einem Server, günstig, aber die Nachbarn beeinflussen dich. VPS (virtueller privater Server): dein eigener Teil eines Servers mit garantierten Ressourcen. Cloud: Du zahlst, was du verbrauchst, und wächst, wenn du es brauchst. Dedizierter Server: eine ganze Maschine nur für dich. Die Wahl hängt vom Verkehr, von den nötigen Ressourcen und vom Budget ab.
Sieh es dir an
Die Adresse und ihre Teile
Die Adresse einer Seite heißt URL (Uniform Resource Locator). Sie sagt alles, was nötig ist, um zur Seite zu kommen. In der Dokumentation triffst du auch den allgemeineren Namen URI (Uniform Resource Identifier), daher kommt der Name der Klasse. In C# gibt dir die Klasse Uri die Teile:
Uri address = new Uri("https://shop.example.bg:8443/products?category=coffee&page=2");Console.WriteLine("Schema: " + address.Scheme);Console.WriteLine("Host: " + address.Host);Console.WriteLine("Port: " + address.Port);Console.WriteLine("Pfad: " + address.AbsolutePath);Console.WriteLine("Query: " + address.Query);
Uri home = new Uri("https://shop.example.bg/");Console.WriteLine("Standardport: " + home.Port);Schema: httpsHost: shop.example.bgPort: 8443Pfad: /productsQuery: ?category=coffee&page=2Standardport: 443- Schema (
https): welches Protokoll. - Host (
shop.example.bg): welcher Computer. Der Name geht durch DNS. - Port (
8443): welches Programm darauf. Wenn er nicht in der Adresse steht, ist es der Standardport des Schemas: 443 fürhttps, 80 fürhttp. - Pfad (
/products): welche Ressource auf dem Server. - Query (
?category=coffee&page=2): zusätzliche Parameter als Paarename=value, getrennt durch&.
Was gibt das Programm aus?
Uri cart = new Uri("http://shop.example.bg/cart?step=2");Console.WriteLine(cart.Port + " " + cart.AbsolutePath);Das Schema ist http, und der Port steht nicht da, also ist er 80. AbsolutePath ist nur der Pfad, ohne die Query nach ?.
Genauer, für Neugierige
- Eine Adresse darf nur lateinische Buchstaben, Ziffern und einige Zeichen enthalten. Alles andere, etwa Buchstaben mit Akzent und Leerzeichen, wird als UTF-8-Bytes mit einem
%davor geschrieben. Der Browser zeigt dir „Café Crème“, aber über das Netz geht die kodierte Form:
Uri search = new Uri("https://shop.example.bg/search?q=Café Crème");Console.WriteLine(search.AbsoluteUri);Console.WriteLine(Uri.UnescapeDataString(search.Query));https://shop.example.bg/search?q=Caf%C3%A9%20Cr%C3%A8me?q=Café Crème- Nach dem Pfad kann auch ein Fragment stehen:
#reviews. Es erreicht den Server nie: Der Browser scrollt die Seite nur zu diesem Teil.
Die Idee
Eine HTTP-Anfrage
Der Browser hat sich verbunden. Jetzt schickt er eine HTTP-Anfrage (Request; HyperText Transfer Protocol). Die Anfrage ist Text:
GET /products?category=coffee HTTP/1.1Host: shop.example.bgAccept: text/htmlUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) Firefox/131.0- Die erste Zeile ist die Methode, der Pfad und die Version. Die Methode sagt, was du willst:
GETist „gib mir“,POSTist „hier sind Daten“ (eine Bestellung, ein Formular). Es gibt auchPUT(ersetzen),DELETE(löschen) und andere. - Dann kommen die Header, einer pro Zeile:
name: value.Hostsagt, welche Website du willst, weil ein Server viele Websites beherbergen kann.Acceptsagt, was der Browser versteht, undUser-Agent, wer er ist. - Eine Leerzeile beendet die Header. Danach kann ein Body kommen: die Daten der Anfrage.
GEThat keinen Body,POSTmeistens schon:
POST /cart HTTP/1.1Host: shop.example.bgContent-Type: application/x-www-form-urlencodedContent-Length: 19
product=C-101&qty=2Content-Length sagt, wie viele Bytes der Body hat, damit der Server weiß, wann er alles empfangen hat.
Die Idee
Eine HTTP-Antwort
Der Server antwortet mit derselben Art von Text (Response). Die erste Zeile trägt den Status: eine Zahl und eine kurze Erklärung. Die erste Ziffer sagt dir die Art:
| Status | Art | Beispiel |
|---|---|---|
| 2xx | Erfolg | 200 OK: Hier ist, was du wolltest |
| 3xx | Weiterleitung | 301 Moved Permanently: Es ist jetzt unter einer anderen Adresse |
| 4xx | Fehler in der Anfrage | 404 Not Found: So etwas gibt es nicht |
| 5xx | Fehler auf dem Server | 500 Internal Server Error: Das Programm auf dem Server ist gescheitert |
Danach kommen die Header der Antwort und der Body: das HTML der Seite, JSON mit Daten, ein Bild.
HTTP/1.1 404 Not FoundContent-Type: text/html; charset=utf-8Content-Length: 37
<h1>Dieses Produkt gibt es nicht</h1>Content-Type sagt, was der Body ist und in welcher Kodierung. Bei einer Weiterleitung gibt der Header Location die neue Adresse an, und der Browser schickt von selbst eine neue Anfrage dorthin:
HTTP/1.1 301 Moved PermanentlyLocation: https://shop.example.bg/productsGenauer, für Neugierige
- HTTP hat kein Gedächtnis (es ist zustandslos, stateless): Jede Anfrage steht für sich, und der Server erinnert sich nicht an die früheren. Damit die Website sich im Warenkorb an dich „erinnert“, gibt sie dir ein Cookie: einen Header, den der Browser bei jeder folgenden Anfrage zurückschickt.
- Ein DDoS-Angriff über HTTP nutzt genau dieses fehlende Gedächtnis: Tausende infizierte Computer schicken eine riesige Zahl von Anfragen an einen Server. Jede sieht normal aus, und der Server muss sie bearbeiten, bis er auch mit den echten Kunden nicht mehr mitkommt. Die Abwehr sitzt vor dem Server: Dienste, die verdächtigen Verkehr filtern und die Zahl der Anfragen von einer Adresse begrenzen.
Sieh es dir an
Die Antwort, mit Code zerlegt
Eine Antwort ist nur Text, also kannst du sie mit String-Methoden zerlegen. Jede Zeile in HTTP endet mit \r\n, und die Leerzeile zwischen Headern und Body ist \r\n\r\n:
string response = "HTTP/1.1 200 OK\r\n" + "Content-Type: text/html; charset=utf-8\r\n" + "Content-Length: 21\r\n" + "\r\n" + "<h1>Café Crème</h1>";
string[] parts = response.Split("\r\n\r\n");string[] lines = parts[0].Split("\r\n");string[] status = lines[0].Split(' ', 3);Console.WriteLine("Version: " + status[0]);Console.WriteLine("Status: " + status[1] + " (" + status[2] + ")");
Dictionary<string, string> headers = new Dictionary<string, string>();for (int i = 1; i < lines.Length; i++){ string[] header = lines[i].Split(": ", 2); headers[header[0]] = header[1];}Console.WriteLine("Typ: " + headers["Content-Type"]);Console.WriteLine("Länge: " + headers["Content-Length"] + " Bytes");Console.WriteLine("Body: " + parts[1]);Version: HTTP/1.1Status: 200 (OK)Typ: text/html; charset=utf-8Länge: 21 BytesBody: <h1>Café Crème</h1>Split("\r\n\r\n")teilt sie in zwei: den Header-Teil und den Body.- Der Header-Teil wird in Zeilen geteilt. Die erste ist der Status.
Split(' ', 3)gibt höchstens 3 Teile: So bleibt bei404 Not Founddie Erklärung ganz. - Die Header kommen in ein Dictionary: Name → Wert.
Split(": ", 2)teilt nur beim ersten:.
Jedes Programm, das HTTP spricht, arbeitet so. In der nächsten Lektion erledigt HttpClient das für dich.
Genauer, für Neugierige
Content-Lengthist 21 Bytes, aber der Text hat 19 Zeichen. Über das Netz reisen UTF-8-Bytes, und dort braucht jeder Buchstabe mit Akzent, wieéoderè, 2 Bytes:
string body = "<h1>Café Crème</h1>";Console.WriteLine(body.Length + " Zeichen");Console.WriteLine(System.Text.Encoding.UTF8.GetByteCount(body) + " Bytes");19 Zeichen21 Bytes- Header-Namen hängen nicht von Groß- und Kleinschreibung ab:
content-typeundContent-Typesind dasselbe. Ein Dictionary, das so vergleicht, baust du mitnew Dictionary<string, string>(StringComparer.OrdinalIgnoreCase). - HTTP/1.1 ist Text. Die neueren HTTP/2 und HTTP/3 schicken dieselben Methoden, Header und Status, aber in binärer Form und mit vielen Anfragen über eine Verbindung. Für dein Programm ist die Bedeutung dieselbe.
Probier es aus
Ein Header mit Doppelpunkt
Das Programm soll Name und Wert des Headers ausgeben, aber statt der Adresse gibt es nur https aus. In welcher Zeile ist der Fehler?
Wähle die Zeile mit dem Fehler.
Split(':') schneidet an jedem Doppelpunkt, und die Adresse hat noch einen, nach https. Es gibt drei Teile: Location, https und //shop.example.bg/products. Also teilst du nur beim ersten: line.Split(": ", 2).
Die Idee
HTTPS: dasselbe, aber abgeschlossen
HTTP ist reiner Text. Jeder Router auf dem Weg kann dein Passwort lesen oder den Preis ändern. HTTPS ist HTTP über TLS (der ältere Name ist SSL):
- Handshake. Browser und Server einigen sich, wie verschlüsselt wird, und tauschen Schlüssel aus.
- Zertifikat. Der Server zeigt ein Zertifikat, unterschrieben von einer Organisation, der der Browser vertraut. So weißt du, dass du mit dem echten
shop.example.bgsprichst und nicht mit jemandem dazwischen. - Verschlüsselung. Ab dann reisen Anfragen und Antworten verschlüsselt. Unterwegs sieht jeder, zu welchem Server du gehst, aber nicht, was ihr euch sagt.
Methoden, Header und Status sind dieselben wie bei HTTP. Das Schloss in der Adressleiste bedeutet, dass die Verbindung über HTTPS läuft.
Die Idee
Was der Browser tut
Die erste Antwort ist HTML: der Text und die Struktur der Seite. Der Browser liest es und findet darin weitere Ressourcen: Stile (CSS), Programme (JavaScript), Bilder, Schriften. Für jede schickt er eine neue Anfrage. Eine gewöhnliche Seite macht Dutzende Anfragen, bevor sie fertig ist. Deshalb lädt eine Website mit vielen schweren Bildern langsam, auch wenn ihr HTML klein ist.
Dann ordnet der Browser alles an und zeichnet es auf den Bildschirm. JavaScript kann die Seite danach ändern, ohne sie neu zu laden.
Genauer, für Neugierige
- Ein Browser hat mehrere Teile. Die Benutzeroberfläche: die Adressleiste, die Buttons, die Lesezeichen, alles außer der Seite selbst. Die Browser-Engine verbindet die Oberfläche mit der Rendering-Engine, die HTML und CSS versteht und zeichnet. Der Netzwerkteil macht die HTTP-Anfragen. Eine Zeichenschicht für einfache Steuerelemente (Aufklapplisten, Fenster), auf allen Betriebssystemen gleich. Der JavaScript-Interpreter führt die Skripte aus. Der Speicher hält Cookies und Daten der Websites (
localStorage, IndexedDB). - Wie das Zeichnen funktioniert: Aus dem HTML baut der Browser einen Baum der Elemente (das DOM), aus dem CSS einen Baum der Stile (das CSSOM). Zusammen ergeben die beiden den Render-Baum. Dann berechnet er, wo jedes Element hinkommt und wie groß es ist (Layout), und zum Schluss zeichnet er (Paint). JavaScript ändert das DOM, und der Browser zeichnet nur das neu, was betroffen ist.
- Zum Weiterlesen: Wie das Internet funktioniert, Ein Überblick über HTTP, Wie Browser funktionieren und HTTP-Flood-DDoS-Angriffe.
Übung
Adressen, Status und Anfragen
Löse die Aufgaben in deinem Editor.
1. Teile einer Adresse. Gib für https://shop.example.bg/search?q=espresso&max=30&page=2 Host, Port und Pfad aus. Dann teile die Query in Paare in einem Dictionary (TrimStart('?') entfernt das Fragezeichen, dann Split('&') und Split('=')), gib sie aus und hol die Seitenzahl als Zahl:
Host: shop.example.bg, Port 443Pfad: /searchq = espressomax = 30page = 2Seite: 22. Was der Status bedeutet. Eine Methode Meaning(int code) mit einem switch gibt die Bedeutung der bekannten Codes 200, 201, 301, 404 und 500 zurück. Für die anderen gibt sie die Art nach der ersten Ziffer (code / 100), und für eine unbekannte Art gibt sie „unbekannter Code“ zurück:
200: Erfolg201: erstellt301: dauerhaft verschoben404: keine solche Ressource418: Fehler in der Anfrage500: Serverfehler503: anderer Serverfehler3. Bau eine Anfrage. Eine Methode BuildGet(Uri address) gibt den Text einer GET-Anfrage mit Host und Accept: text/html zurück, mit \r\n am Ende jeder Zeile und einer Leerzeile am Schluss. address.PathAndQuery gibt den Pfad zusammen mit der Query. Gib sie aus und ersetze dabei jedes \r\n durch den sichtbaren Text \r\n und einen Zeilenumbruch:
GET /products?category=tea HTTP/1.1\r\nHost: shop.example.bg\r\nAccept: text/html\r\n\r\nTest
Teste dich
Verwandte Lektionen
Abschnitt „Verwandte Lektionen“- Baut auf: Parameter und return · Klassen und Objekte · static: was alle Objekte teilen · Listen, Dictionaries und LINQ
- Geht weiter in: Ein Webserver mit Minimal API · MVC: Model, View, Controller · Views mit Razor · WebAPI: Daten für andere Programme
- Aufgaben zum Thema: Web und Desktop