Deux applications peuvent-elles écouter le même port?

283

Deux applications sur la même machine peuvent-elles se lier au même port et à la même adresse IP? Pour aller plus loin, une application peut-elle écouter les demandes provenant d'une certaine IP et l'autre vers une autre IP distante? Je sais que je peux avoir une application qui démarre deux threads (ou fourches) pour avoir un comportement similaire, mais deux applications qui n'ont rien en commun peuvent-elles faire de même?

nadiv
la source
2
Pour une bonne réponse détaillée sur la réutilisation des adresses / ports avec plusieurs sockets: stackoverflow.com/questions/14388706/…
Bjarke Freund-Hansen

Réponses:

248

La réponse diffère selon le système d'exploitation envisagé. En général cependant:

Pour TCP, non. Vous ne pouvez avoir qu'une seule application à l'écoute sur le même port à la fois. Maintenant, si vous aviez 2 cartes réseau, vous pourriez avoir une application écouter sur la première IP et la seconde sur la deuxième IP en utilisant le même numéro de port.

Pour UDP (Multicasts), plusieurs applications peuvent s'abonner au même port.

Edit: Depuis Linux Kernel 3.9 et versions ultérieures, la prise en charge de plusieurs applications écoutant le même port a été ajoutée à l'aide de l' SO_REUSEPORToption. Plus d'informations sont disponibles sur cet article lwn.net.

Chris Dail
la source
22
«une seule application à l'écoute sur un seul port» est la raison pour laquelle des ports existent - pour permettre à plusieurs applications de partager le réseau sans conflits.
S.Lott
46
Un écouteur par port par adresse IP. L'ajout d'une autre interface réseau est un moyen d'obtenir une deuxième adresse IP. Votre plateforme prend probablement en charge les interfaces virtuelles, ce qui est un autre moyen d'obtenir deux adresses IP avec une carte réseau physique.
John M
7
Bien que j'étais du même avis jusqu'à présent, il s'avère que j'ai pu lier deux processus différents au même port ip et TCP! Cela est possible si vous définissez ServerSocket.setReuseAddress (true) en Java avant de le lier. Comportement vraiment inattendu.
Eugen
7
(1) Le sens réel de votre réponse est «Pour TCP, oui, condition que ...» (2) La multidiffusion n'est pas une condition préalable au partage de port UDP, mais SO_REUSEADDR l'est.
Marquis de Lorne
12
Pour UDP (Multicasts), plusieurs applications peuvent s'abonner au même port. Si un paquet est arrivé du client, quelle application le reçoit?
Yang Juven
123

Oui (pour TCP), deux programmes peuvent écouter sur la même socket, si les programmes sont conçus pour cela. Lorsque le socket est créé par le premier programme, assurez-vous que l' SO_REUSEADDRoption est définie sur le socket avant vous bind(). Cependant, ce n'est peut-être pas ce que vous voulez. Ce que cela fait, c'est qu'une connexion TCP entrante sera dirigée vers l' un des programmes, pas les deux, donc elle ne duplique pas la connexion, elle permet simplement à deux programmes de répondre à la demande entrante. Par exemple, les serveurs Web auront plusieurs processus écoutant tous sur le port 80, et l'O / S envoie une nouvelle connexion au processus qui est prêt à accepter de nouvelles connexions.

SO_REUSEADDR

Permet à d'autres sockets d'accéder à bind()ce port, sauf s'il existe déjà un socket d'écoute actif lié au port. Cela vous permet de contourner ces messages d'erreur «Adresse déjà utilisée» lorsque vous essayez de redémarrer votre serveur après un plantage.

JNewton
la source
1
TCP + UDP fonctionne désormais (avec un noyau suffisamment nouveau). Voir le lien que j'ai ajouté à la réponse.
dpb
3
Cette réponse n'est pas correcte à moins que tous les sockets soient liés à des adresses IP distinctes dont aucune n'est INADDR_ANY, ou à moins que vous soyez sous Windows, où le résultat n'est pas défini.
Marquis de Lorne
1
Pouvez-vous développer la façon dont les données sont transmises à une application spécifique sur le même port? Y a-t-il des problèmes de sécurité à considérer lorsque les applications utilisent SO_REUSEADDR ou SO_REUSEPORT?
trusktr
@EJP Pouvez-vous également jeter un œil à mon commentaire précédent?
trusktr
3
SO_REUSEADDRne vous permet certainement pas d'avoir deux sockets TCP en état d'écoute en même temps, au moins sur Unix. Il est destiné à contourner le TIME_WAIT state: unixguide.net/network/socketfaq/4.5.shtml . Cela peut fonctionner sur Windows, mais vous n'êtes pas garanti que la demande atteindra le bon serveur de toute façon).
Bruno
48

Oui.

  1. Plusieurs sockets TCP d'écoute, tous liés au même port, peuvent coexister, à condition qu'ils soient tous liés à différentes adresses IP locales. Les clients peuvent se connecter à celui dont ils ont besoin. Cela exclut 0.0.0.0( INADDR_ANY).

  2. Plusieurs sockets acceptés peuvent coexister, tous acceptés à partir du même socket d'écoute, tous affichant le même numéro de port local que le socket d'écoute.

  3. Plusieurs sockets UDP tous liés au même port peuvent tous coexister à condition que la même condition soit en (1) ou qu'ils aient tous eu l' SO_REUSEADDRoption définie avant la liaison.

  4. Les ports TCP et les ports UDP occupent des espaces de noms différents, de sorte que l'utilisation d'un port pour TCP n'empêche pas son utilisation pour UDP, et vice versa.

Référence: Stevens & Wright, TCP / IP Illustrated, Volume II.

Marquis de Lorne
la source
avez-vous un lien à portée de main? L'opportunité de la coexistence TCP-UDP est ma question même. Merci d'avance :)
Wolf
1
@Wolf Essayez-le. C'est toute la preuve dont vous avez vraiment besoin. Ma citation est Stevens & Wright: vous ne pouvez pas faire mieux que ça.
Marquis de Lorne
1
Merci pour la réponse, je dois lire encore plus attentivement. Vous avez déjà écrit que UDP et TCP peuvent coexister .
Wolf
47

En principe, non.

Ce n'est pas écrit dans la pierre; mais c'est la façon dont toutes les API sont écrites: l'application ouvre un port, obtient un descripteur et le système d'exploitation le notifie (via ce descripteur) lorsqu'une connexion client (ou un paquet dans le cas UDP) arrive.

Si le système d'exploitation permettait à deux applications d'ouvrir le même port, comment saurait-il laquelle notifier?

Mais ... il existe des moyens de contourner cela:

  1. Comme l'a noté Jed , vous pouvez écrire un processus «maître», qui serait le seul à vraiment écouter sur le port et à en informer les autres, en utilisant la logique qu'il souhaite pour séparer les demandes des clients.
    • Sur Linux et BSD (au moins), vous pouvez configurer des règles de «remappage» qui redirigent les paquets du port «visible» vers différents ports (où les applications écoutent), en fonction de tous les critères liés au réseau (peut-être le réseau d'origine, ou certains formes simples d'équilibrage de charge).
Javier
la source
37
iptables -m statistic --mode random --probability 0.5est drole.
Jed Smith
1
Que signifie exactement "Ouvre un port"? Je comprends la phrase, mais savez-vous exactement ce que fait le système lorsqu'il ouvre un port et le gère? Je sais que lorsque vous voulez ouvrir un port avec TCP, vous obtenez un flux et ce flux est votre connexion avec la télécommande, mais je recherche sur le Web et je n'ai pas trouvé de très bonne explication.
Samuel
4
@Samuel: ouvrir un port (en mode serveur) signifie obtenir un descripteur de fichier, et lorsque le système reçoit un paquet SYN vers ce numéro de port, répond avec SYN + ACK et génère un événement sur le descripteur de fichier associé. l'application répond à cet événement avec un appel accept (), qui crée un nouveau descripteur de fichier associé au flux spécifique, laissant le descripteur de serveur d'origine libre pour obtenir de nouvelles connexions des clients
Javier
7
Cette réponse ne peut pas être considérée comme correcte. Il ignore entièrement l'existence de SO_REUSEADDR et SO_REUSEPORT.
Marquis de Lorne
@Javier Non, ce n'est pas le cas. L'ouverture d'un port du point de vue de l'application serveur se produit lorsque vous liez le socket d'écoute, ou plutôt liez le socket sur lequel vous vous apprêtez listen(). Plus probablement, la question est de l'ouvrir dans le pare-feu. Beaucoup trop d'erreurs ici, et toutes non corrigées en 7 ans. La réponse omet également le cas de la liaison à une adresse locale différente avec le même numéro de port. C'est en fait totalement incorrect.
Marquis de Lorne
27

Oui certainement . Pour autant que je m'en souvienne A partir de la version 3.9 du noyau (je ne suis pas sûr de la version), le support pour le a SO_REUSEPORTété introduit. SO_RESUEPORTpermet de se lier au même port et à la même adresse, Tant que le premier serveur définit cette option avant de lier son socket.

Cela fonctionne pour TCP et UDP . Reportez-vous au lien pour plus de détails: SO_REUSEPORT

Remarque : la réponse acceptée n'est plus vraie selon moi.

piyush
la source
2
Totalement vrai. Si ce n'était pas vrai, comment Wireshark pourrait-il fonctionner?
Staszek
5
@Staszek Wireshark n'écoute pas les ports. Il fonctionne au niveau des paquets.
Marquis de Lorne
Oh, ça aurait du sens. Quoi qu'il en soit, l'écoute de deux ports par 2 applications est sûrement possible.
Staszek
18

Non. Une seule application peut se lier à un port à la fois et le comportement si la liaison est forcée est indéterminé.

Avec les sockets multicast - qui ne ressemblent en rien à ce que vous voulez - plus d'une application peut se lier à un port tant que SO_REUSEADDR est défini dans les options de chaque socket.

Vous pouvez accomplir cela en écrivant un processus "maître", qui accepte et traite toutes les connexions, puis les transmet à vos deux applications qui doivent écouter sur le même port. C'est l'approche que les serveurs Web et autres adoptent, car de nombreux processus doivent écouter 80.

Au-delà de cela, nous entrons dans les détails - vous avez marqué à la fois TCP et UDP, quel est-il? Et quelle plateforme?

Jed Smith
la source
les deux m'intéressent. La plate-forme est Windows, mais si la réponse est différente pour Linux, ce serait bien de savoir
nadiv
8
Il n'existe pas de socket multicast. Il existe des sockets UDP. La multidiffusion n'est pas une condition préalable à SO_REUSEADDR.
Marquis de Lorne
3

Vous pouvez avoir une application à l'écoute sur un port pour une interface réseau. Vous pourriez donc avoir:

  1. httpd écoute sur une interface accessible à distance, p.ex. 192.168.1.1:80
  2. un autre démon écoute 127.0.0.1:80

Un exemple de cas d'utilisation pourrait être d'utiliser httpdcomme équilibreur de charge ou proxy.

Tomas Tomecek
la source
3

Une autre manière est d'utiliser un programme d'écoute dans un port qui analyse le type de trafic (ssh, https, etc.) qu'il redirige en interne vers un autre port sur lequel le "vrai" service écoute.

Par exemple, pour Linux, sslh: https://github.com/yrutschle/sslh

Mitchbcn
la source
Existe-t-il un tel programme sur Windows? J'ai besoin que mon serveur IIS local et mon courtier ActiveMQ écoutent sur le port 443
Harvey Lin
3

Lorsque vous créez une connexion TCP, vous demandez de vous connecter à une adresse TCP spécifique, qui est une combinaison d'une adresse IP (v4 ou v6, selon le protocole que vous utilisez) et d'un port.

Lorsqu'un serveur écoute les connexions, il peut informer le noyau qu'il souhaite écouter une adresse IP et un port spécifiques, c'est-à-dire une adresse TCP, ou sur le même port sur chacune des adresses IP de l'hôte (généralement spécifié avec l'adresse IP 0.0.0.0), qui écoute efficacement de nombreuses "adresses TCP" différentes (par exemple 192.168.1.10:8000,127.0.0.1:8000 , etc.)

Non, vous ne pouvez pas avoir deux applications écoutant la même "adresse TCP", car lorsqu'un message arrive, comment le noyau pourrait-il savoir à quelle application transmettre le message?

Cependant, dans la plupart des systèmes d'exploitation, vous pouvez configurer plusieurs adresses IP sur une seule interface (par exemple, si vous avez 192.168.1.10une interface, vous pouvez également configurer 192.168.1.11, si personne d'autre sur le réseau ne l'utilise), et dans ces cas, vous pourrait avoir des applications distinctes écoutant sur le port 8000de chacune de ces deux adresses IP.

cjs
la source
2

Si au moins une des adresses IP distantes est déjà connue, statique et dédiée à ne parler qu'à l'une de vos applications, vous pouvez utiliser la règle iptables (table nat, chaîne PREROUTING) pour rediriger le trafic entrant de cette adresse vers le port local "partagé" vers tout autre port où l'application appropriée écoute réellement.

Stemar
la source
1

Oui et non. Une seule application peut écouter activement sur un port. Mais cette application peut léguer sa connexion à un autre processus. Vous pouvez donc avoir plusieurs processus travaillant sur le même port.

Rajesh
la source
@trusktr, je pense qu'il pensait cela
warvariuc
1

Oui.

De cet article:
https://lwn.net/Articles/542629/

La nouvelle option de socket permet à plusieurs sockets sur le même hôte de se lier au même port

user6169806
la source
1
Beau lien, mais cette ligne n'y est pas écrite - L' option SO_REUSEPORT n'est pas standard
Sahil Singh
0

Si par applications, vous entendez plusieurs processus, alors oui, mais généralement NON. Par exemple, le serveur Apache exécute plusieurs processus sur le même port (généralement 80), en désignant l'un des processus pour se lier réellement au port, puis en utilisant ce processus pour effectuer des transferts vers divers processus qui acceptent les connexions.

nitinsh99
la source
0

Vous pouvez faire en sorte que deux applications écoutent le même port sur la même interface réseau.

Il ne peut y avoir qu'un seul socket d'écoute pour l'interface réseau et le port spécifiés, mais ce socket peut être partagé entre plusieurs applications.

Si vous avez un socket d'écoute dans un processus d'application et vous forkce processus, le socket sera hérité, donc techniquement il y aura maintenant deux processus écoutant le même port.

warvariuc
la source
0

J'ai essayé ce qui suit, avec socat:

socat TCP-L:8080,fork,reuseaddr -

Et même si je n'ai pas établi de connexion avec le socket, je ne peux pas écouter deux fois sur le même port, malgré l' reuseaddroption.

Je reçois ce message (auquel je m'attendais auparavant):

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

Juste pour partager ce que @jnewton a mentionné. J'ai commencé un nginx et un processus tomcat intégré sur mon mac. Je peux voir les deux processus s'exécuter à 8080.

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

Réponse courte:

En passant par la réponse donnée ici . Vous pouvez avoir deux applications écoutant sur la même adresse IP et le même numéro de port, tant l'un des ports est un port UDP, tandis que l'autre est un port TCP.

Explication:

Le concept de port est pertinent sur la couche de transport de la pile TCP / IP, donc tant que vous utilisez différents protocoles de couche de transport de la pile, vous pouvez avoir plusieurs processus à l'écoute sur le même <ip-address>:<port> combinaison.

Un doute que les gens ont est que si deux applications s'exécutent sur la même <ip-address>:<port>combinaison, comment un client s'exécutant sur une machine distante fera-t-il la distinction entre les deux? Si vous regardez l'en-tête du paquet de couche IP ( https://en.wikipedia.org/wiki/IPv4#Header ), vous verrez que les bits 72 à 79 sont utilisés pour définir le protocole, c'est ainsi que la distinction peut être faite.

Si toutefois vous voulez avoir deux applications sur la même <ip-address>:<port>combinaison TCP , la réponse est non (un exercice intéressant sera de lancer deux machines virtuelles, de leur donner la même adresse IP, mais des adresses MAC différentes, et de voir ce qui se passe - vous remarquerez que parfois VM1 recevra des paquets, et d'autres fois VM2 recevra des paquets - en fonction de l'actualisation du cache ARP).

Je pense qu'en faisant fonctionner deux applications sur le même <op-address>:<port> vous voulez obtenir une sorte d'équilibrage de charge. Pour cela, vous pouvez exécuter les applications sur différents ports et écrire des règles de table IP pour bifurquer le trafic entre elles.

Voir également la réponse de @ user6169806.

Sahil Singh
la source