Wie lautet der Wiederzusammensetzungspfad einer HTTP-Antwort?

478
cg14

Ich versuche zu verstehen, wie Betriebssysteme das erneute Zusammenstellen von Netzwerkanforderungen generell implementieren. Nach meinem besten Verständnis trifft Folgendes zu:

Eine HTTP-Anforderung wird auf Anwendungsebene unter Verwendung einer HTTP-Bibliothek gestellt. Diese HTTP-Bibliothek ist wirklich ein Wrapper für einige Socket-Implementierungen des Betriebssystems.

Ein "sendender" Socket wird unter Verwendung des Ziels und der Quelle der HTTP-Anforderung instanziiert.

Ein "empfangender" Socket wird mit der IP-Adresse des Geräts und einem randomisierten (freien) Port instanziiert.

Die HTTP-Nachricht wird mit der Dateibeschreibung des Socket "Übertragen" gesendet.

Die Sende-Methode des Sockets sendet die Nachricht an die TCP-Implementierung des Betriebssystems.

Die TCP-Implementierung segmentiert die HTTP-Nachricht, wobei der Zielport (bei der Instantiierung des Sockets angegeben) und der Quellport vorangestellt werden. (Ich gehe davon aus, dass dies abhängig von der Implementierung irgendwie weitergegeben wird.) Sobald die HTTP-Nachricht segmentiert und die TCP-Header angehängt wurden, werden die TCP-Segmente an die IP-Implementierung des Betriebssystems übergeben.

Den TCP-Segmenten werden IP-Header vorangestellt. Die IP-Zieladresse wurde beim Instantiieren des Sockets angegeben. (Wieder gehe ich davon aus, dass die Quell-IP-Adresse je nach Implementierung weitergegeben wird.)

Die IP-Pakete werden dann mit Ethernet-Headern umhüllt, an den Router gesendet, an den Server gesendet, der Server verarbeitet die Anfrage und sendet die Antwort zurück.

Hier bricht mein Verständnis darüber zusammen, was genau im Wiederherstellungsprozess passiert.

Wie kommt die Antwort zurück zum Empfangspuffer des "empfangenden" Sockets, mehrmals, wenn das IP-Paket das Gerät zurücksendet?

Offensichtlich fallen Header ab, aber welche Schritte werden unternommen, um speziell auf den Empfangspuffer des "empfangenden" Sockets und dann vom Socket zurück zur Anwendung zu gelangen?

PS Ich hoffe auf mehr technische Details als nur "IP setzt es neu zusammen" oder "TCP setzt es wieder zusammen" und gibt es an die nächste Schicht weiter. Ich hoffe zu verstehen, wie genau dies geschieht und nicht nur theoretisch (obwohl ich es verstehe, ist es OS-spezifisch).

Bearbeiten:

Um das Thema klarer zu machen, möchte ich darauf hinweisen, dass meine Verweise auf Socket und alle Socket-Methoden auf das Linux-Betriebssystem verweisen.

0
Kommentare sind nicht für eine erweiterte Diskussion vorgesehen. Dieses Gespräch wurde [zum Chat verschoben] (https://chat.stackexchange.com/rooms/79429/discussion-on-question-by-cg14-what-is-the-reassembly-path-of-a-http- Antwort). Journeyman Geek vor 6 Jahren 0

2 Antworten auf die Frage

1
cg14

Eine gute Entdeckung von Mike Penningtion (in den Kommentaren ), in der Sie eine detaillierte technische Beschreibung des Pfads einer Anforderung auf dem Network Stack finden und sichern (speziell für Linux OS 2005).

Ein genauerer Blick, wo die folgenden Schritte extrahiert wurden :

Beachten Sie, dass die aufgeführten Schritte bei weitem nicht so detailliert sind wie das oben erwähnte Dokument.

Das Betriebssystem verfügt über einen speziellen Dateideskriptor für den Ethernet-RX-Port.

The rx ring is a ring in the kernel memory where the network card transfers the incoming packet through DMA. The raw data which is stored in the rx ring structure is either copied into a sk buff structure. 

Daraufhin wird eine ISR ausgelöst, um das Paket auf die Netzwerkschicht zu verschieben. Beachten Sie, dass hier festgelegt wird, ob das Paket verarbeitet oder weitergeleitet werden soll (was interessant war, wie ich mir vorstellen kann, wie das Aktivieren der Weiterleitung funktioniert, wie für VPNs).

Wenn gültig, wird es auf die IP-Schicht verschoben. Er prüft sein Protokoll (vom IP-Header) und ruft die tcp v4 rcvFunktion auf, wenn TCP das Protokoll ist, und bewegt sich auf die TCP-Schicht.

Und dieser Teil ist entscheidend:

The next step for this function is to find an open socket for this incoming packet, 

Dies geschieht durch Aufruf des tcp v4 lookup, im folgenden Codesegment:

sk = __tcp_v4_lookup(skb->nh.iph->saddr, th->source, skb->nh.iph->daddr, ntohs(th->dest), tcp_v4_iif(skb)); 

Im Wesentlichen ist festzustellen, dass es eine LUT gibt, die den TCP-Socket der Quell- und Zieladresse / den Ports der Socketverbindung zuordnet, wie durch diesen Funktionsaufruf angegeben.

Wenn ein gültiger Socket vorhanden ist, werden die Daten in tcp_data_queueden Stack eingefügt, um den Anwendungsverbrauch zu erhöhen.

0
Mike Pennington

(aus den Kommentaren )

Ich bekomme Kapselung. Nehmen wir an, das Betriebssystem verfügt über einen dedizierten Dateideskriptor, der auf dem dedizierten Ethernet-Rx-Port geöffnet ist. Es entfernt den Ethernet-Header von einem Frame und übergibt ihn an eine IP-Analysefunktion, um die Ziel-IP zu entfernen. Es fügt dies in eine Struktur ein und sendet es und die Struktur an die TCP-Schicht. Hier wird es vom Zielport entfernt und in derselben Struktur abgelegt. Hier muss eine Zuordnung zu dem Socket-Dateideskriptor basierend auf Port und IP vorgenommen werden, um die Daten in einen Puffer zu stellen, der dem Dateideskriptor zugewiesen ist. Das ist meine beste Sache. Aber ich würde gerne wissen, was tatsächlich passiert.

Eine ziemlich alte Version dessen, was Sie suchen, ist hier: Linux-Netzwerkstack . Ich versuche, etwas neueres als eine Beschreibung aus dem Jahr 2005 zu finden, da sich einige der Linux-Mutationen seitdem geändert haben. Die meisten Socket-Pufferinformationen werden in einer Struktur namens sk_buffa gespeichert. Hierbei handelt es sich um eine Linux-Struktur, die Zeiger auf den TCP-Socket-Handle sowie alle Socket-Lese- / Schreibpuffer enthält.

Wenn der Linux-NIC-Treiber Informationen von der NIC zu einem bestimmten Socket erhält, sucht er den Pufferbereich der sk_buffInstanz (benannt skb) und gibt die Daten in die Puffer aus, auf die der skb.