Wie funktioniert die Socket-API-Funktion accept ()?

126

Die Socket-API ist der De-facto-Standard für TCP / IP- und UDP / IP-Kommunikation (dh Netzwerkcode, wie wir ihn kennen). Eine seiner Kernfunktionen accept()ist jedoch etwas magisch.

So leihen Sie sich eine semi-formale Definition aus:

accept () wird auf der Serverseite verwendet. Es akzeptiert einen empfangenen eingehenden Versuch, eine neue TCP-Verbindung vom Remote-Client zu erstellen, und erstellt einen neuen Socket, der dem Socket-Adresspaar dieser Verbindung zugeordnet ist.

Mit anderen Worten, acceptgibt einen neuen Socket zurück, über den der Server mit dem neu verbundenen Client kommunizieren kann. Der alte Socket (an dem er acceptaufgerufen wurde) bleibt am selben Port geöffnet und wartet auf neue Verbindungen.

Wie funktioniert das accept? Wie ist es implementiert? Es gibt viel Verwirrung zu diesem Thema. Viele Leute behaupten, dass Akzeptieren einen neuen Port öffnet und Sie über diesen mit dem Client kommunizieren. Dies ist jedoch offensichtlich nicht der Fall, da kein neuer Port geöffnet wird. Sie können tatsächlich über denselben Port mit verschiedenen Clients kommunizieren, aber wie? Wenn mehrere Threads recvdenselben Port aufrufen , woher wissen die Daten, wohin sie gehen sollen?

Ich denke, es ist etwas in der Art, wie die Adresse des Kunden mit einem Socket-Deskriptor verknüpft ist, und wann immer Daten eingehen, werden recvsie an den richtigen Socket weitergeleitet, aber ich bin mir nicht sicher.

Es wäre großartig, eine gründliche Erklärung des Innenlebens dieses Mechanismus zu erhalten.

Eli Bendersky
quelle
2
Daher wird für jede Clientanforderung eine brandneue Socket-Verbindung am Serverende geöffnet. Der Server muss immer bei 80 geöffnet sein, um auf eingehende Anrufe zu warten. Wenn es einen Anruf erhält, erstellt es sofort einen NEUEN Socket mit den vier unten genannten Tupeln, der eine TCP-Verbindung zwischen Client und Server herstellt. Ist mein Verständnis richtig?
Gehirn Sturm
1
Dies ist eine sehr grundsätzliche Frage , und ich war auf dieser in einem Interview vor kurzem getestet: stackoverflow.com/questions/24871827/... Wenn Sie Kommentare zu diesem Thema haben, bitte posten
Brain Storm
@brainstorm Nur wenn Sie die Existenz von HTTP Keep-Alive vollständig ignorieren.
Marquis von Lorne

Antworten:

140

Ihre Verwirrung liegt in der Annahme, dass ein Socket durch Server IP: Server Port identifiziert wird. In Wirklichkeit werden Steckdosen durch ein Informationsquartett eindeutig identifiziert:

Client IP : Client Port und Server IP : Server Port

Während die Server-IP und der Server-Port in allen akzeptierten Verbindungen konstant sind, können sie anhand der clientseitigen Informationen verfolgen, wohin alles führt.

Beispiel zur Klärung:

Sagen wir an einen Server 192.168.1.1:80und zwei Clients, 10.0.0.1und 10.0.0.2.

10.0.0.1Öffnet eine Verbindung am lokalen Port 1234und stellt eine Verbindung zum Server her. Jetzt hat der Server einen Socket, der wie folgt identifiziert wird:

10.0.0.1:1234 - 192.168.1.1:80  

Jetzt 10.0.0.2öffnet eine Verbindung zu lokal Port 5678und einer Verbindung zum Server. Jetzt verfügt der Server über zwei Sockets, die wie folgt gekennzeichnet sind:

10.0.0.1:1234 - 192.168.1.1:80  
10.0.0.2:5678 - 192.168.1.1:80
17 von 26
quelle
3
Ich kenne die Implementierungsdetails nicht (die wahrscheinlich von Plattform zu Plattform variieren), ich weiß nur, dass die Sockets konzeptionell durch das von mir beschriebene Informationsquartett identifiziert werden.
17 von 26
3
Haben Sie einen Hinweis darauf?
Qeek
3
Zufällige Frage: Was passiert, wenn NAT verwendet wird und zwei Clients im selben Netzwerk versuchen, denselben lokalen Port zu verwenden, wenn sie eine Verbindung zum Server herstellen? Wenn beispielsweise 10.0.0.1 und 10.0.0.2 beide mit einem Router mit einer externen IP von 192.168.0.1 verbunden sind, sieht der Server unter 192.168.1.1 zwei Verbindungen von 192.168.0.1. Was passiert in diesem Fall, wenn durch einen Zufall des Zufallszahlengenerators sowohl 10.0.0.1 als auch 10.0.0.2 denselben lokalen Port wählen?
Aroth
4
Die NAT-Unterstützung im Router kümmert sich dort um die Details. Der Netzwerkverkehr wird tatsächlich über zwei Verbindungen geleitet - Client zu Router und Router zu Server. Der Router stellt die ausgehenden Verbindungen an zwei verschiedenen Ports 192.168.0.1:1234 und 192.168.0.1:5678 her. Der eingehende Datenverkehr wird dann vom Router an den richtigen Client umgeleitet.
17 vom 26.
3
Wenn das Quartett eine Steckdose identifiziert, wie lauten die Quartettinformationen einer Hörbuchse?
Eric Zheng
74

Nur um die Antwort des Benutzers "17 von 26" zu ergänzen.

Der Socket besteht tatsächlich aus 5 Tupeln (Quell-IP, Quell-Port, Ziel-IP, Ziel-Port, Protokoll). Hier könnte das Protokoll TCP oder UDP oder ein beliebiges Transportschichtprotokoll sein. Dieses Protokoll wird im Paket aus dem Feld 'Protokoll' im IP-Datagramm identifiziert.

Somit ist es möglich, dass unterschiedliche Anwendungen auf dem Server mit genau denselben 4-Tupeln, jedoch unterschiedlich im Protokollfeld, mit demselben Client kommunizieren müssen. Beispielsweise

Apache auf der Serverseite spricht weiter (server1.com:880-client1:1234 auf TCP) und World of Warcraft spricht weiter (server1.com:880-client1:1234 auf UDP)

Sowohl der Client als auch der Server behandeln dies, da das Protokollfeld im IP-Paket in beiden Fällen unterschiedlich ist, selbst wenn alle anderen 4 Felder gleich sind.

Methos
quelle
13

Was mich verwirrte, als ich dies lernte, war, dass die Begriffe socketund portsuggerieren, dass sie etwas Physisches sind, obwohl es sich tatsächlich nur um Datenstrukturen handelt, die der Kernel verwendet, um die Details der Vernetzung zu abstrahieren.

Als solche werden die Datenstrukturen implementiert, um Verbindungen von verschiedenen Clients trennen zu können. In Bezug auf , wie sie umgesetzt sind, dann ist die Antwort entweder a.) Spielt es keine Rolle, der Zweck der Sockets API genau ist , dass die Umsetzung nicht Materie oder b sollte.) Nur einen Blick. Schauen Sie sich neben den sehr empfohlenen Stevens-Büchern, die eine detaillierte Beschreibung einer Implementierung enthalten, die Quelle in Linux oder Solaris oder einem der BSDs an.

a2800276
quelle
Ja, der größte Teil der Netzwerkterminologie weist nur bestimmten Sammlungen von Bits und Entscheidungen, die auf der Grundlage ihrer Werte getroffen werden ("Protokollkennung", "Routing", "Bindung", "Socket" usw.), Namen zu. Die gesamte Hardware Ihrer Netzwerkkarte ist für den Empfang von Bits ausgelegt. Was mit ihnen in Bezug auf Programme auf Ihrem Computer passiert, wird vom Treiber und vom Betriebssystem festgelegt. Wir könnten all diese Terminologie morgen loswerden, wenn wir wollten, aber das Prinzip, einen Strom von Bits zu liefern, scheint grundlegend zu sein ...
masterxilo
-1

Wie der andere sagte, wird ein Socket durch ein 4-Tupel (Client-IP, Client-Port, Server-IP, Server-Port) eindeutig identifiziert.

Der Serverprozess, der auf der Server-IP ausgeführt wird, verwaltet eine Datenbank (dh es ist mir egal, welche Art von Tabelle / Liste / Baum / Array / magische Datenstruktur er verwendet) mit aktiven Sockets und überwacht den Server-Port. Wenn eine Nachricht empfangen wird (über den TCP / IP-Stack des Servers), werden die Client-IP und der Port mit der Datenbank verglichen. Wenn die Client-IP und der Client-Port in einem Datenbankeintrag gefunden werden, wird die Nachricht an einen vorhandenen Handler übergeben. Andernfalls wird ein neuer Datenbankeintrag erstellt und ein neuer Handler für diesen Socket erstellt.

In den frühen Tagen des ARPAnet haben bestimmte Protokolle (FTP für einen) einen bestimmten Port auf Verbindungsanfragen abgehört und mit einem Handoff-Port geantwortet. Weitere Kommunikationen für diese Verbindung würden über den Handoff-Port erfolgen. Dies wurde durchgeführt, um die Leistung pro Paket zu verbessern: Computer waren damals um mehrere Größenordnungen langsamer.


quelle
Können Sie den Teil "Übergabeport" näher erläutern?
Eli Bendersky
1
Dies ist entweder eine Beschreibung eines Pre-TCP-Protokolls oder zu stark vereinfacht. Ein Client, der versucht, eine Verbindung zu einem Listening-Socket herzustellen, sendet ein spezielles Paket, um die Verbindung herzustellen (SYN-Bit gesetzt). Es gibt eine klare Unterscheidung zwischen einem Paket, das einen neuen Socket erstellt, und einem Paket, das einen vorhandenen Socket verwendet.
John M
... sendet ein spezielles Paket, um die Verbindung herzustellen (SYN-Bit gesetzt). Was (so wie ich es verstehe) dazu führt, dass der Protokollstapel es dem 'Listener' (falls vorhanden) gibt, weshalb es nur einen Listening-Port pro Adresse / Port / Protokoll-Kombination geben kann. Ich bin mir nicht sicher, ob dies in der Spezifikation oder nur in der Implementierungskonvention enthalten ist.
Peter Wone
1
Der zweite Absatz beschreibt nicht korrekt, was entweder auf der TCP-Ebene oder innerhalb eines Serverprozesses geschieht. Serverprozesse müssen keine Datenstrukturen von Sockets jeglicher Art verwalten oder eingehende IP: Port-Paare gegen irgendetwas überprüfen. Dafür gibt es Steckdosen. FTP verwendet einen separaten Port für Daten, nicht für alle "weiteren Kommunikationen", und dient der Vereinfachung des Protokolls, nicht aus Leistungsgründen. Verwenden Sie einen neuen Port, ohne die Leistung in irgendeiner Weise zu verbessern.
Marquis von Lorne
"unterhält eine Datenbank (was bedeutet, dass es mir egal ist, welche Art von Tabelle / Liste / Baum / Array / magischer Datenstruktur sie verwendet)" :) Ich nenne dies normalerweise eine "Tabelle" (oder vielleicht "Grafik" oder "Entscheidungsbaum") ). "Datenbank" schlägt mir eine Implementierung vor.
Masterxilo