Dies mag eine sehr grundlegende Frage sein, aber sie verwirrt mich.
Können sich zwei verschiedene angeschlossene Sockets einen Port teilen? Ich schreibe einen Anwendungsserver, der mehr als 100.000 gleichzeitige Verbindungen verarbeiten kann, und wir wissen, dass die Anzahl der auf einem System verfügbaren Ports etwa 60.000 (16 Bit) beträgt. Ein verbundener Socket wird einem neuen (dedizierten) Port zugewiesen. Dies bedeutet, dass die Anzahl der gleichzeitigen Verbindungen durch die Anzahl der Ports begrenzt ist, es sei denn, mehrere Sockets können denselben Port gemeinsam nutzen. Also die Frage.
Vielen Dank für die Hilfe im Voraus!
TCP / HTTP-Überwachung von Ports: Wie können viele Benutzer denselben Port gemeinsam nutzen?
Was passiert also, wenn ein Server an einem TCP-Port auf eingehende Verbindungen wartet? Angenommen, Sie haben einen Webserver an Port 80. Nehmen wir an, Ihr Computer hat die öffentliche IP-Adresse 24.14.181.229 und die Person, die versucht, eine Verbindung zu Ihnen herzustellen, hat die IP-Adresse 10.1.2.3. Diese Person kann eine Verbindung zu Ihnen herstellen, indem sie einen TCP-Socket bis 24.14.181.229:80 öffnet. Einfach genug.
Intuitiv (und fälschlicherweise) gehen die meisten Leute davon aus, dass es ungefähr so aussieht:
Dies ist intuitiv, da er aus Sicht des Clients eine IP-Adresse hat und unter IP: PORT eine Verbindung zu einem Server herstellt. Da der Client eine Verbindung zu Port 80 herstellt, muss sein Port auch 80 sein? Dies ist eine vernünftige Sache zu denken, aber eigentlich nicht, was passiert. Wenn das richtig wäre, könnten wir nur einen Benutzer pro fremder IP-Adresse bedienen. Sobald ein Remotecomputer eine Verbindung hergestellt hat, würde er die Verbindung von Port 80 zu Port 80 blockieren, und niemand anderes könnte eine Verbindung herstellen.
Drei Dinge müssen verstanden werden:
1.) Auf einem Server lauscht ein Prozess auf einem Port. Sobald eine Verbindung hergestellt wurde, wird sie an einen anderen Thread übergeben. Die Kommunikation belastet niemals den Abhörport.
2.) Verbindungen werden vom Betriebssystem durch das folgende 5-Tupel eindeutig identifiziert: (lokale IP, lokaler Port, Remote-IP, Remote-Port, Protokoll). Wenn ein Element im Tupel anders ist, ist dies eine völlig unabhängige Verbindung.
3.) Wenn ein Client eine Verbindung zu einem Server herstellt, wählt er einen zufälligen, nicht verwendeten Quellport höherer Ordnung aus . Auf diese Weise kann ein einzelner Client für denselben Zielport bis zu ~ 64.000 Verbindungen zum Server haben.
Das wird also wirklich erstellt, wenn ein Client eine Verbindung zu einem Server herstellt:
Betrachten, was tatsächlich passiert
Lassen Sie uns zunächst netstat verwenden, um zu sehen, was auf diesem Computer geschieht. Wir werden Port 500 anstelle von 80 verwenden (da auf Port 80 eine ganze Reihe von Dingen passiert, da es sich um einen gemeinsamen Port handelt, aber funktional macht es keinen Unterschied).
Wie erwartet ist die Ausgabe leer. Starten wir nun einen Webserver:
Hier ist die Ausgabe von netstat:
Jetzt gibt es einen Prozess, der aktiv auf Port 500 lauscht (Status: LISTEN). Die lokale Adresse lautet 0.0.0.0. Dies ist der Code für "Lauschen auf alle IP-Adressen". Ein leichter Fehler besteht darin, nur Port 127.0.0.1 abzuhören, der nur Verbindungen vom aktuellen Computer akzeptiert. Dies ist also keine Verbindung. Dies bedeutet lediglich, dass ein Prozess zum Binden () an Port-IP angefordert wird und dieser Prozess für die Verarbeitung aller Verbindungen zu diesem Port verantwortlich ist. Dies weist auf die Einschränkung hin, dass es nur einen Prozess pro Computer geben kann, der einen Port überwacht (es gibt Möglichkeiten, dies mithilfe von Multiplexing zu umgehen, dies ist jedoch ein viel komplizierteres Thema). Wenn ein Webserver Port 80 überwacht, kann er diesen Port nicht für andere Webserver freigeben.
Lassen Sie uns nun einen Benutzer mit unserer Maschine verbinden:
Dies ist ein einfaches Skript ( https://github.com/grokit/quickweb ), das einen TCP-Socket öffnet, die Nutzdaten sendet (in diesem Fall "Nutzdaten testen"), einige Sekunden wartet und die Verbindung trennt. Wenn Sie netstat erneut ausführen, während dies geschieht, wird Folgendes angezeigt:
Wenn Sie eine Verbindung mit einem anderen Client herstellen und netstat erneut ausführen, wird Folgendes angezeigt:
... das heißt, der Client hat einen anderen zufälligen Port für die Verbindung verwendet. Es gibt also nie Verwechslungen zwischen den IP-Adressen.
quelle
Das ist eine verbreitete Intuition, aber falsch. Ein angeschlossener Socket ist keinem neuen / dedizierten Port zugeordnet. Die einzige tatsächliche Einschränkung, die der TCP-Stapel erfüllen muss, besteht darin, dass das Tupel (local_address, local_port, remote_address, remote_port) für jede Socket-Verbindung eindeutig sein muss. Somit kann der Server viele TCP-Sockets haben, die denselben lokalen Port verwenden, solange jeder der Sockets am Port mit einem anderen Remote-Standort verbunden ist.
Siehe den Abschnitt "Socket Pair" unter: http://books.google.com/books?id=ptSC4LpwGA0C&lpg=PA52&dq=socket%20pair%20tuple&pg=PA52#v=onepage&q=socket%20pair%20tuple&f=false
quelle
bind()
Operation derconnect()
Operation sogar implizit vorausgeht .bind()
wird nur auf der Serverseite verwendet, bevoraccept()?
also die Clientseite auch den jeweiligen Port bindet?bind()
kann vorher auf der Client-Seite verwendet werdenconnect()
.Theoretisch ja. Übe nicht. Die meisten Kernel (inkl. Linux) erlauben Ihnen keine Sekunde
bind()
zu einem bereits zugewiesenen Port. Es war kein wirklich großer Patch, dies zuzulassen.Konzeptionell sollten wir zwischen Socket und Port unterscheiden . Sockets sind bidirektionale Kommunikationsendpunkte, dh "Dinge", an denen wir Bytes senden und empfangen können. Es ist eine konzeptionelle Sache, es gibt kein solches Feld in einem Paket-Header mit dem Namen "Socket".
Port ist eine Kennung, die einen Socket identifizieren kann. Im Fall von TCP ist ein Port eine 16-Bit-Ganzzahl, es gibt jedoch auch andere Protokolle (bei Unix-Sockets ist ein "Port" im Wesentlichen eine Zeichenfolge).
Das Hauptproblem ist das Folgende: Wenn ein eingehendes Paket eintrifft, kann der Kernel seinen Socket anhand seiner Zielportnummer identifizieren. Dies ist der häufigste Weg, aber nicht die einzige:
Da Sie an einem Anwendungsserver arbeiten, kann dieser dies tun.
quelle
bind()
.bind()
? Ich kann es mir vorstellen, ja, es ist durchaus möglich, aber Tatsache ist, dass sowohl WinSock als auch die Posix-API denbind()
Aufruf dafür verwenden, selbst wenn ihre Parametrisierung praktisch gleich ist. Auch wenn eine API diesen Aufruf nicht hat, müssen Sie ihn irgendwie sagen, von wo aus Sie die eingehenden Bytes lesen möchten .listen()
/accept()
API-Aufrufe können die Sockets so erstellen, dass der Kernel sie durch ihre eingehenden Ports unterscheidet. Die Frage des OP kann so interpretiert werden, wie er es im Wesentlichen verlangt. Ich denke, es ist ziemlich realistisch, aber nicht das ist es, was seine Frage wörtlich bedeutet.Nein. Es ist nicht möglich, denselben Port zu einem bestimmten Zeitpunkt gemeinsam zu nutzen. Sie können Ihre Anwendung jedoch so gestalten, dass der Portzugriff zu einem anderen Zeitpunkt erfolgt.
quelle