Können zwei Anwendungen denselben Port abhören?

283

Können zwei Anwendungen auf demselben Computer an denselben Port und dieselbe IP-Adresse gebunden werden? Kann eine App noch einen Schritt weitergehen und Anfragen von einer bestimmten IP-Adresse und die andere von einer anderen Remote-IP-Adresse abhören? Ich weiß, dass ich eine Anwendung haben kann, die zwei Threads (oder Gabeln) startet, um ein ähnliches Verhalten zu haben, aber können zwei Anwendungen, die nichts gemeinsam haben, dasselbe tun?

nadiv
quelle
2
Für eine gute detaillierte Antwort zur Wiederverwendung von Adressen / Ports mit mehreren Sockets: stackoverflow.com/questions/14388706/…
Bjarke Freund-Hansen

Antworten:

248

Die Antwort hängt davon ab, welches Betriebssystem in Betracht gezogen wird. Im Allgemeinen jedoch:

Für TCP nein. Es kann immer nur eine Anwendung gleichzeitig denselben Port überwachen. Wenn Sie nun zwei Netzwerkkarten hätten, könnte eine Anwendung die erste IP und die zweite die zweite IP mit derselben Portnummer abhören.

Bei UDP (Multicasts) können mehrere Anwendungen denselben Port abonnieren.

Bearbeiten: Seit Linux Kernel 3.9 und höher wurde die Unterstützung für mehrere Anwendungen hinzugefügt, die denselben Port SO_REUSEPORTabhören. Weitere Informationen finden Sie in diesem Artikel von lwn.net.

Chris Dail
quelle
22
"Eine Anwendung überwacht einen einzelnen Port" ist der Grund, warum Ports vorhanden sind, damit mehrere Anwendungen das Netzwerk ohne Konflikte gemeinsam nutzen können.
S.Lott
46
Ein Listener pro Port pro IP-Adresse. Durch Hinzufügen einer weiteren Netzwerkschnittstelle können Sie eine zweite IP-Adresse abrufen. Ihre Plattform unterstützt wahrscheinlich virtuelle Schnittstellen. Dies ist eine weitere Möglichkeit, zwei IP-Adressen mit einer physischen Netzwerkkarte abzurufen.
John M
7
Obwohl ich bis jetzt der gleichen Meinung war, stellte sich heraus, dass ich zwei verschiedene Prozesse an denselben IP- und TCP-Port binden konnte! Dies ist möglich, wenn Sie ServerSocket.setReuseAddress (true) in Java festlegen, bevor Sie eine Bindung herstellen. Wirklich unerwartetes Verhalten.
Eugen
7
(1) Die eigentliche Bedeutung Ihrer Antwort lautet "Für TCP ja, vorausgesetzt ...". (2) Multicast ist keine Voraussetzung für die gemeinsame Nutzung von UDP-Ports, SO_REUSEADDR jedoch.
Marquis von Lorne
12
Bei UDP (Multicasts) können mehrere Anwendungen denselben Port abonnieren. Wenn ein Paket vom Client eingetroffen ist, welche Anwendung erhält es?
Yang Juven
123

Ja (für TCP) Sie können zwei Programme auf demselben Socket abhören lassen, wenn die Programme dafür ausgelegt sind. Wenn der Socket vom ersten Programm erstellt wird, stellen Sie sicher, dass die SO_REUSEADDROption am Socket vor Ihnen festgelegt ist bind(). Dies ist jedoch möglicherweise nicht das, was Sie möchten. Dies bedeutet, dass eine eingehende TCP-Verbindung an eines der Programme geleitet wird, nicht an beide, sodass die Verbindung nicht dupliziert wird. Es können lediglich zwei Programme die eingehende Anforderung bearbeiten. Beispielsweise haben Webserver mehrere Prozesse, die alle auf Port 80 lauschen, und das Betriebssystem sendet eine neue Verbindung an den Prozess, der bereit ist, neue Verbindungen zu akzeptieren.

SO_REUSEADDR

Ermöglicht anderen Sockets den Anschluss bind()an diesen Port, es sei denn, an den Port ist bereits ein aktiver Listening-Socket gebunden. Auf diese Weise können Sie die Fehlermeldungen "Adresse wird bereits verwendet" umgehen, wenn Sie versuchen, Ihren Server nach einem Absturz neu zu starten.

JNewton
quelle
1
TCP + UDP funktioniert jetzt (vorausgesetzt, der Kernel ist neu genug). Siehe den Link, den ich zur Antwort hinzugefügt habe.
dpb
3
Diese Antwort ist nicht korrekt, es sei denn, alle Sockets sind an unterschiedliche IP-Adressen gebunden, von denen keine INADDR_ANY ist, oder Sie arbeiten unter Windows, wo das Ergebnis undefiniert ist.
Marquis von Lorne
1
Können Sie erläutern, wie die Daten an eine bestimmte App am selben Port gesendet werden? Gibt es Sicherheitsbedenken, über die Sie nachdenken sollten, wenn Apps SO_REUSEADDR oder SO_REUSEPORT verwenden?
Trusktr
@EJP Kannst du dir auch meinen vorherigen Kommentar ansehen?
Trusktr
3
SO_REUSEADDRAuf keinen Fall können Sie zwei TCP-Sockets gleichzeitig im Empfangsstatus haben, zumindest unter Unix. Es soll das umgehenTIME_WAIT state : unixguide.net/network/socketfaq/4.5.shtml . Es könnte unter Windows funktionieren, aber Sie können nicht garantieren, dass die Anfrage trotzdem den richtigen Server erreicht.
Bruno
48

Ja.

  1. Mehrere abhörende TCP-Sockets, die alle an denselben Port gebunden sind, können nebeneinander existieren, sofern sie alle an unterschiedliche lokale IP-Adressen gebunden sind. Kunden können sich mit jedem verbinden, den sie benötigen. Dies schließt 0.0.0.0( INADDR_ANY) aus.

  2. Es können mehrere akzeptierte Sockets nebeneinander existieren, die alle von demselben Listening-Socket akzeptiert werden und alle dieselbe lokale Portnummer wie der Listening-Socket anzeigen.

  3. Mehrere UDP-Sockets, die alle an denselben Port gebunden sind, können nebeneinander existieren, sofern entweder dieselbe Bedingung wie unter (1) vorliegt oder für alle SO_REUSEADDRvor dem Binden die Option festgelegt wurde.

  4. TCP-Ports und UDP-Ports belegen unterschiedliche Namespaces, sodass die Verwendung eines Ports für TCP die Verwendung für UDP nicht ausschließt und umgekehrt.

Referenz: Stevens & Wright, TCP / IP Illustrated, Band II.

Marquis von Lorne
quelle
Hast du einen Link zur Hand? Die Möglichkeit der Koexistenz von TCP und UDP ist meine Frage. Danke im Voraus :)
Wolf
1
@ Wolf Versuch es einfach. Das ist der Beweis, den Sie wirklich brauchen. Mein Zitat ist Stevens & Wright: Besser geht es nicht.
Marquis von Lorne
1
Vielen Dank für die Antwort, ich muss noch aufmerksamer lesen. Sie haben bereits geschrieben, dass UDP und TCP koexistieren können .
Wolf
47

Im Prinzip nein.

Es ist nicht in Stein gemeißelt; Aber es ist die Art und Weise, wie alle APIs geschrieben werden: Die App öffnet einen Port, erhält ein Handle dafür und das Betriebssystem benachrichtigt ihn (über dieses Handle), wenn eine Clientverbindung (oder ein Paket im UDP-Fall) eintrifft.

Wenn das Betriebssystem zwei Apps erlauben würde, denselben Port zu öffnen, wie würde es wissen, welche zu benachrichtigen sind?

Aber ... es gibt Möglichkeiten, dies zu umgehen:

  1. Als Jed bemerkte , könnten Sie einen "Master" -Prozess schreiben, der der einzige ist, der den Port wirklich abhört und andere benachrichtigt, indem Sie jede Logik verwenden, die Clientanforderungen trennen soll.
    • Unter Linux und BSD können Sie (zumindest) "Remapping" -Regeln einrichten, die Pakete vom "sichtbaren" Port zu anderen (wo die Apps lauschen) umleiten, und zwar nach netzwerkbezogenen Kriterien (z. B. dem Ursprungsnetzwerk oder einem anderen) einfache Formen des Lastausgleichs).
Javier
quelle
37
iptables -m statistic --mode random --probability 0.5macht Spaß.
Jed Smith
1
Was genau bedeutet "Öffnet einen Port"? Ich verstehe den Satz, aber wissen Sie genau, was das System tut, wenn es einen Port öffnet und damit umgeht? Ich weiß, wenn Sie einen Port mit TCP öffnen möchten, erhalten Sie einen Stream und dieser Stream ist Ihre Verbindung mit der Fernbedienung, aber ich suche im Web und habe keine sehr gute Erklärung gefunden.
Samuel
4
@Samuel: Das Öffnen eines Ports (im Servermodus) bedeutet, dass ein Dateideskriptor abgerufen wird. Wenn das System ein SYN-Paket an diese Portnummer erhält, antwortet es mit SYN + ACK und generiert ein Ereignis für den zugehörigen Dateideskriptor. Die Anwendung reagiert auf dieses Ereignis mit einem accept () -Aufruf, der einen neuen Dateideskriptor erstellt, der dem jeweiligen Stream zugeordnet ist, sodass der ursprüngliche Serverdeskriptor frei bleibt, um neue Verbindungen von Clients zu erhalten
Javier
7
Diese Antwort kann nicht als richtig angesehen werden. Es wird die Existenz von SO_REUSEADDR und SO_REUSEPORT völlig übersehen.
Marquis von Lorne
@ Javier Nein, tut es nicht. Das Öffnen eines Ports aus Sicht der Serveranwendung erfolgt, wenn Sie den Listening-Socket bzw. den Socket binden, an dem Sie sich gerade befinden listen(). Wahrscheinlich geht es darum, es in der Firewall zu öffnen. Viel zu viele Fehler hier und alle in 7 Jahren unkorrigiert. Bei der Antwort wird auch der Fall der Bindung an eine andere lokale Adresse mit derselben Portnummer weggelassen. Es ist in der Tat völlig falsch.
Marquis von Lorne
27

Ja auf jeden Fall . Soweit ich mich erinnere, wurde ab Kernel Version 3.9 (bei der Version nicht sicher) die Unterstützung für das SO_REUSEPORTeingeführt. SO_RESUEPORTErmöglicht die Bindung an genau denselben Port und dieselbe Adresse, solange der erste Server diese Option vor dem Binden seines Sockets festlegt.

Es funktioniert sowohl für TCP als auch für UDP . Weitere Informationen finden Sie unter dem Link: SO_REUSEPORT

Hinweis : Die akzeptierte Antwort gilt meiner Meinung nach nicht mehr.

piyush
quelle
2
Völlig wahr. Wenn es nicht wahr wäre, wie könnte Wireshark funktionieren?
Staszek
5
@Staszek Wireshark hört keine Ports ab. Es arbeitet auf Paketebene.
Marquis von Lorne
Oh, das würde Sinn machen. Auf jeden Fall ist es sicher möglich, zwei Ports von zwei Apps abzuhören.
Staszek
18

Nein. Es kann jeweils nur eine Anwendung an einen Port gebunden werden. Das Verhalten beim Erzwingen der Bindung ist unbestimmt.

Bei Multicast-Sockets, die nicht annähernd Ihren Wünschen entsprechen, kann mehr als eine Anwendung an einen Port gebunden werden, solange SO_REUSEADDR in den Optionen der einzelnen Sockets festgelegt ist.

Sie können dies erreichen, indem Sie einen "Master" -Prozess schreiben, der alle Verbindungen akzeptiert und verarbeitet und sie dann an Ihre beiden Anwendungen weitergibt, die denselben Port überwachen müssen. Dies ist der Ansatz, den Webserver und dergleichen verfolgen, da viele Prozesse 80 abhören müssen.

Darüber hinaus gehen wir auf Einzelheiten ein - Sie haben sowohl TCP als auch UDP markiert, was ist das? Auch welche Plattform?

Jed Smith
quelle
beide interessieren mich. Die Plattform ist Windows, aber wenn die Antwort für Linux anders ist, wäre es schön zu wissen
Nadiv
8
Es gibt keinen Multicast-Socket. Es gibt UDP-Sockets. Multicast ist keine Voraussetzung für SO_REUSEADDR.
Marquis von Lorne
3

Sie können eine Anwendung an einem Port auf eine Netzwerkschnittstelle warten lassen. Deshalb könnten Sie haben:

  1. httpd Abhören über eine fernzugängliche Schnittstelle, z 192.168.1.1:80
  2. ein anderer Daemon hört zu 127.0.0.1:80

Ein Beispiel für einen Anwendungsfall könnte die Verwendung httpdals Load Balancer oder Proxy sein.

Tomas Tomecek
quelle
3

Eine andere Möglichkeit besteht darin, ein Programm zu verwenden, das an einem Port lauscht und die Art des Datenverkehrs (ssh, https usw.) analysiert, den es intern an einen anderen Port umleitet, an dem der "echte" Dienst lauscht.

Für Linux beispielsweise sslh: https://github.com/yrutschle/sslh

Mitchbcn
quelle
Gibt es ein solches Programm unter Windows? Ich muss sowohl meinen lokalen IIS-Server als auch den ActiveMQ-Broker auf Port 443
Harvey Lin
3

Wenn Sie eine TCP-Verbindung erstellen, werden Sie aufgefordert, eine Verbindung zu einer bestimmten TCP-Adresse herzustellen. Dies ist eine Kombination aus einer IP-Adresse (v4 oder v6, je nach verwendetem Protokoll) und einem Port.

Wenn ein Server auf Verbindungen wartet, kann er den Kernel darüber informieren, dass er eine bestimmte IP-Adresse und einen bestimmten Port abhören möchte, dh eine TCP-Adresse oder denselben Port an jeder IP-Adresse des Hosts (normalerweise mit IP-Adresse angegeben) 0.0.0.0), die effektiv viele verschiedene "TCP-Adressen" abhört (z 192.168.1.10:8000.127.0.0.1:8000 usw.)

Nein, Sie können nicht zwei Anwendungen haben, die dieselbe "TCP-Adresse" abhören, denn wenn eine Nachricht eingeht, wie würde der Kernel wissen, an welche Anwendung die Nachricht gesendet werden soll?

In den meisten Betriebssystemen können Sie jedoch mehrere IP-Adressen auf einer einzigen Schnittstelle einrichten (z. B. wenn Sie 192.168.1.10eine Schnittstelle haben, können Sie diese auch einrichten 192.168.1.11, wenn niemand anderes im Netzwerk sie verwendet), und in diesen Fällen auch Sie Möglicherweise haben separate Anwendungen den Port 8000für jede dieser beiden IP-Adressen abgehört .

cjs
quelle
2

Wenn mindestens eine der Remote-IPs bereits bekannt, statisch und nur für die Kommunikation mit einer Ihrer Apps vorgesehen ist, können Sie mithilfe der iptables-Regel (Tabelle nat, Ketten-PREROUTING) eingehenden Datenverkehr von dieser Adresse an den "freigegebenen" lokalen Port umleiten Jeder andere Port, an dem die entsprechende Anwendung tatsächlich empfangsbereit ist.

Stemar
quelle
1

Ja und nein. Nur eine Anwendung kann einen Port aktiv überwachen. Diese Anwendung kann jedoch ihre Verbindung zu einem anderen Prozess hinterlassen. Es können also mehrere Prozesse an demselben Port arbeiten.

Rajesh
quelle
@trusktr, ich denke, er meinte das
warvariuc
1

Ja.

Aus diesem Artikel:
https://lwn.net/Articles/542629/

Mit der neuen Socket-Option können mehrere Sockets auf demselben Host an denselben Port gebunden werden

user6169806
quelle
1
Netter Link, jedoch nicht diese Zeile dort geschrieben - Die Option SO_REUSEPORT ist nicht Standard
Sahil Singh
0

Wenn Sie unter Anwendungen mehrere Prozesse verstehen, dann ja, aber im Allgemeinen NEIN. Zum Beispiel führt der Apache-Server mehrere Prozesse auf demselben Port aus (im Allgemeinen 80). Dazu wird einer der Prozesse so festgelegt, dass er tatsächlich an den Port gebunden wird, und dieser Prozess wird dann verwendet, um Übergaben an verschiedene Prozesse durchzuführen, die Verbindungen akzeptieren.

nitinsh99
quelle
0

Sie können zwei Anwendungen veranlassen, auf denselben Port auf derselben Netzwerkschnittstelle zu warten.

Es kann nur einen Überwachungssocket für die angegebene Netzwerkschnittstelle und den angegebenen Port geben, dieser Socket kann jedoch von mehreren Anwendungen gemeinsam genutzt werden.

Wenn Sie in einem Anwendungsprozess einen Listening-Socket haben und forkdiesen Prozess ausführen, wird der Socket vererbt, sodass technisch gesehen jetzt zwei Prozesse denselben Port überwachen.

warvariuc
quelle
0

Ich habe folgendes versucht mit socat:

socat TCP-L:8080,fork,reuseaddr -

Und obwohl ich keine Verbindung zum Socket hergestellt habe, kann ich trotz des nicht zweimal auf demselben Port lauschen reuseaddr Option .

Ich bekomme diese Nachricht (die ich vorher erwartet hatte):

2016/02/23 09:56:49 socat[2667] E bind(5, {AF=2 0.0.0.0:8080}, 16): Address already in use
aDoN
quelle
0

Nur um zu teilen, was @jnewton erwähnt hat. Ich habe einen Nginx- und einen eingebetteten Tomcat-Prozess auf meinem Mac gestartet. Ich kann beide Prozesse bei 8080 laufen sehen.

LT<XXXX>-MAC:~ b0<XXX>$ sudo netstat -anp tcp | grep LISTEN
tcp46      0      0  *.8080                 *.*                    LISTEN     
tcp4       0      0  *.8080                 *.*                    LISTEN   
Amit Parashar
quelle
-2

Kurze Antwort:

Gehen Sie nach der hier gegebenen Antwort . Sie können zwei Anwendungen haben, die dieselbe IP-Adresse und Portnummer abhören, solange einer der Ports ein UDP-Port ist, während der andere ein TCP-Port ist.

Erläuterung:

Das Konzept des Ports ist auf der Transportschicht des TCP / IP-Stapels relevant. Solange Sie also verschiedene Transportschichtprotokolle des Stapels verwenden, können mehrere Prozesse auf denselben warten <ip-address>:<port> Kombination abhören.

Ein Zweifel, den Menschen haben, ist, wenn zwei Anwendungen auf derselben <ip-address>:<port>Kombination ausgeführt werden, wie wird ein Client, der auf einem Remotecomputer ausgeführt wird, zwischen beiden unterscheiden? Wenn Sie sich den IP-Layer-Paket-Header ansehen ( https://en.wikipedia.org/wiki/IPv4#Header ) , werden Sie sehen, dass die Bits 72 bis 79 zum Definieren des Protokolls verwendet werden. Auf diese Weise kann die Unterscheidung getroffen werden.

Wenn Sie jedoch zwei Anwendungen auf demselben TCP haben möchten <ip-address>:<port> Kombination lautet die Antwort Nein (Eine interessante Übung besteht darin, zwei VMs zu starten, ihnen dieselbe IP-Adresse, aber unterschiedliche MAC-Adressen zu geben und zu sehen, was passiert - das werden Sie manchmal bemerken VM1 erhält Pakete, und zu anderen Zeiten erhält VM2 Pakete (abhängig von der Aktualisierung des ARP-Cache).

Ich habe das Gefühl, dass zwei Anwendungen gleichzeitig ausgeführt werden <op-address>:<port> Sie eine Art Lastausgleich erzielen möchten, . Zu diesem Zweck können Sie die Anwendungen an verschiedenen Ports ausführen und IP-Tabellenregeln schreiben, um den Datenverkehr zwischen ihnen aufzuteilen.

Siehe auch die Antwort von @ user6169806.

Sahil Singh
quelle