Due applicazioni possono ascoltare la stessa porta?


283

Due applicazioni sulla stessa macchina possono associarsi alla stessa porta e indirizzo IP? Facendo un passo avanti, un'app può ascoltare le richieste provenienti da un determinato IP e l'altra a un altro IP remoto? So di poter avere un'applicazione che inizia due thread (o fork) per avere un comportamento simile, ma due applicazioni che non hanno nulla in comune possono fare lo stesso?


2
Per una buona risposta dettagliata sul riutilizzo di indirizzi / porte con più socket: stackoverflow.com/questions/14388706/…
Bjarke Freund-Hansen,

Risposte:


248

La risposta varia a seconda del sistema operativo considerato. In generale però:

Per TCP, n. Puoi avere solo un'applicazione in ascolto sulla stessa porta alla volta. Ora se avessi 2 schede di rete, potresti avere un'applicazione in ascolto sul primo IP e la seconda sul secondo IP usando lo stesso numero di porta.

Per UDP (Multicasts), più applicazioni possono abbonarsi alla stessa porta.

Modifica: da Linux Kernel 3.9 e versioni successive, è stato aggiunto il supporto per più applicazioni che ascoltano la stessa porta utilizzando l' SO_REUSEPORTopzione. Maggiori informazioni sono disponibili in questo articolo di lwn.net.


22
"un'applicazione in ascolto su una singola porta" è il motivo per cui esistono porte - per consentire a più applicazioni di condividere la rete senza conflitti.
S. Lott,

46
Un ascoltatore per porta per indirizzo IP. L'aggiunta di un'altra interfaccia di rete è un modo per ottenere un secondo indirizzo IP. La tua piattaforma probabilmente supporta interfacce virtuali che è un altro modo per ottenere due indirizzi IP con una scheda di rete fisica.
John M,

7
Anche se finora ero della stessa opinione, risulta che sono stato in grado di associare due diversi processi alla stessa porta IP e TCP! Ciò è possibile se si imposta ServerSocket.setReuseAddress (true) in Java prima di eseguire il binding ad esso. Comportamento davvero inaspettato.
Eugen,

7
(1) Il vero significato della tua risposta è 'Per TCP, sì, fornito ...' (2) Multicast non è un prerequisito per la condivisione delle porte UDP, ma SO_REUSEADDR lo è.
Marchese di Lorne,

12
Per UDP (Multicasts), più applicazioni possono abbonarsi alla stessa porta. Se un pacchetto è arrivato dal client, quale applicazione lo riceve?
Yang Juven,

123

Sì (per TCP) è possibile avere due programmi in ascolto sullo stesso socket, se i programmi sono progettati per farlo. Quando il socket viene creato dal primo programma, assicurarsi che l' SO_REUSEADDRopzione sia impostata sul socket prima di voi bind(). Tuttavia, questo potrebbe non essere quello che desideri. Ciò che fa è che una connessione TCP in entrata verrà indirizzata a uno dei programmi, non ad entrambi, quindi non duplica la connessione, ma consente solo a due programmi di soddisfare la richiesta in arrivo. Ad esempio, i server Web avranno più processi tutti in ascolto sulla porta 80 e l'O / S invierà una nuova connessione al processo pronta ad accettare nuove connessioni.

SO_REUSEADDR

Consente ad altri socket di accedere a bind()questa porta, a meno che non sia già presente un socket di ascolto attivo associato alla porta. Ciò consente di aggirare i messaggi di errore "Indirizzo già in uso" quando si tenta di riavviare il server dopo un arresto anomalo.


1
TCP + UDP ora funziona (dato un kernel abbastanza nuovo). Vedi il link che ho aggiunto alla risposta.
dpb,

3
Questa risposta non è corretta a meno che tutti i socket non siano associati a indirizzi IP distinti, nessuno dei quali sia INADDR_ANY o a meno che non ci si trovi su Windows, dove il risultato non è definito.
Marchese di Lorne,

1
Puoi espandere il modo in cui i dati vanno a un'app specifica sulla stessa porta? Ci sono problemi di sicurezza a cui pensare quando le app usano SO_REUSEADDR o SO_REUSEPORT?
trusktr,

@EJP Puoi anche dare un'occhiata al mio commento precedente?
trusktr,

3
SO_REUSEADDRcertamente non ti consente di avere due socket TCP nello stato di ascolto contemporaneamente, almeno su Unix. Ha lo scopo di aggirare TIME_WAIT state: unixguide.net/network/socketfaq/4.5.shtml . Potrebbe funzionare su Windows, ma non sei sicuro che la richiesta raggiungerà comunque il server giusto).
Bruno,

48

Sì.

  1. Più socket TCP in ascolto, tutti associati alla stessa porta, possono coesistere, a condizione che siano tutti associati a indirizzi IP locali diversi. I clienti possono connettersi a quello di cui hanno bisogno. Questo esclude 0.0.0.0( INADDR_ANY).

  2. Possono coesistere più socket accettati , tutti accettati dallo stesso socket di ascolto, mostrando tutti lo stesso numero di porta locale del socket di ascolto.

  3. Più socket UDP tutti associati alla stessa porta possono coesistere a condizione che abbiano le stesse condizioni di (1) oppure tutti hanno l' SO_REUSEADDRopzione impostata prima del bind.

  4. Le porte TCP e UDP occupano spazi dei nomi diversi, quindi l'uso di una porta per TCP non ne preclude l'utilizzo per UDP e viceversa.

Riferimento: Stevens & Wright, TCP / IP Illustrated, Volume II.


hai un link a portata di mano? L'opportunità della convivenza TCP-UDP è la mia vera domanda. Grazie in anticipo :)
Wolf,

1
@ Lupo Basta provarlo. Questa è tutta la prova di cui hai veramente bisogno. La mia citazione è Stevens & Wright: non puoi andare molto meglio di così.
Marchese di Lorne,

1
Grazie per la risposta, ho bisogno di leggere ancora più attento. Hai già scritto che UDP e TCP possono coesistere .
Lupo,

47

In linea di principio, no.

Non è scritto in pietra; ma è il modo in cui tutte le API sono scritte: l'app apre una porta, ne ottiene un handle e il sistema operativo lo notifica (tramite tale handle) quando arriva una connessione client (o un pacchetto nel caso UDP).

Se il sistema operativo consentisse a due app di aprire la stessa porta, come farebbe a sapere quale notificare?

Ma ... ci sono modi per aggirarlo:

  1. Come notato da Jed , potresti scrivere un processo "master", che sarebbe l'unico che ascolta davvero sulla porta e avvisa gli altri, usando qualsiasi logica voglia separare le richieste del client.
    • Su Linux e BSD (almeno) è possibile impostare regole di "rimappatura" che reindirizzano i pacchetti dalla porta "visibile" a diverse (in cui le app sono in ascolto), in base a qualsiasi criterio relativo alla rete (forse la rete di origine, o alcuni forme semplici di bilanciamento del carico).

37
iptables -m statistic --mode random --probability 0.5è divertente.
Jed Smith,

1
Cosa significa esattamente "Apre una porta"? Capisco la frase ma sai cosa fa esattamente il sistema quando apre una porta e la gestisce? So che quando vuoi aprire una porta con TCP, ottieni uno stream e quel flusso è la tua connessione con il telecomando ma io cerco sul web e non trovo un'ottima spiegazione.
Samuel,

4
@Samuel: aprire una porta (in modalità server) significa ottenere un descrittore di file e quando il sistema ottiene un pacchetto SYN a quel numero di porta, risponde con SYN + ACK e genera un evento sul descrittore di file associato. l'applicazione risponde a quell'evento con una chiamata accept (), che crea un nuovo descrittore di file associato allo stream specifico, lasciando libero il descrittore del server originale per ottenere nuove connessioni dai client
Javier

7
Questa risposta non può essere considerata corretta. Trascura completamente l'esistenza di SO_REUSEADDR e SO_REUSEPORT.
Marchese di Lorne,

@Javier No, non lo è. L'apertura di una porta dal punto di vista dell'applicazione server si verifica quando si associa il socket di ascolto, o piuttosto si lega al socket su cui si sta per listen()accedere. Più probabilmente la domanda riguarda l'apertura nel firewall. Troppi errori qui, e tutti non corretti in 7 anni. La risposta omette anche il caso di associazione a un indirizzo locale diverso con lo stesso numero di porta. In realtà è totalmente errato.
Marchese di Lorne,

27

Sì, sicuramente . Per quanto mi ricordo Dal kernel versione 3.9 (Non sono sicuro sulla versione) in poi è SO_REUSEPORTstato introdotto il supporto per il . SO_RESUEPORTconsente l'associazione alla stessa porta e indirizzo esatti, purché il primo server imposti questa opzione prima di associare il suo socket.

Funziona sia per TCP che per UDP . Fare riferimento al collegamento per ulteriori dettagli: SO_REUSEPORT

Nota : la risposta accettata non è più vera secondo la mia opinione.


2
Completamente vero. Se non fosse vero, come potrebbe funzionare Wireshark?
Staszek,

5
@Staszek Wireshark non ascolta le porte. Funziona a livello di pacchetto.
Marchese di Lorne,

Oh, avrebbe senso. Ad ogni modo, è sicuramente possibile ascoltare due porte per 2 app.
Staszek,

18

No. Solo un'applicazione può legarsi a una porta alla volta e il comportamento se il bind viene forzato è indeterminato.

Con i socket multicast - che non sembrano essere vicini a ciò che desideri - più di un'applicazione può collegarsi a una porta purché SO_REUSEADDR sia impostato nelle opzioni di ciascun socket.

Puoi farlo scrivendo un processo "master", che accetta ed elabora tutte le connessioni, quindi le passa alle tue due applicazioni che devono ascoltare sulla stessa porta. Questo è l'approccio adottato dai server Web e simili, poiché molti processi devono ascoltare 80.

Oltre a questo, stiamo entrando nei dettagli: hai taggato sia TCP che UDP, che cos'è? Inoltre, quale piattaforma?


entrambi mi interessano. La piattaforma è Windows, ma se la risposta è diversa per Linux, sarebbe bello saperlo
nadiv

8
Non esiste un socket multicast. Ci sono socket UDP. Il multicast non è un prerequisito per SO_REUSEADDR.
Marchese di Lorne,

3

È possibile avere un'applicazione in ascolto su una porta per un'interfaccia di rete. Pertanto potresti avere:

  1. httpd ascolto su interfaccia accessibile da remoto, ad es 192.168.1.1:80
  2. un altro demone in ascolto 127.0.0.1:80

Il caso d'uso di esempio potrebbe essere l'utilizzo httpdcome bilanciamento del carico o proxy.


3

Un altro modo è utilizzare un programma in ascolto in una porta che analizza il tipo di traffico (ssh, https, ecc.) Che reindirizza internamente a un'altra porta su cui è in ascolto il servizio "reale".

Ad esempio, per Linux, sslh: https://github.com/yrutschle/sslh


Esiste un programma simile su Windows? Ho bisogno che il mio server IIS locale e il broker ActiveMQ siano in ascolto sulla porta 443
Harvey Lin,

3

Quando si crea una connessione TCP, si richiede di connettersi a un indirizzo TCP specifico, che è una combinazione di un indirizzo IP (v4 o v6, a seconda del protocollo in uso) e di una porta.

Quando un server è in ascolto delle connessioni, può informare il kernel che desidera ascoltare un indirizzo IP e una porta specifici, ovvero un indirizzo TCP o sulla stessa porta su ciascuno degli indirizzi IP dell'host (di solito specificato con l'indirizzo IP 0.0.0.0), che è effettivamente in ascolto su un sacco di diversi "indirizzi TCP" (ad esempio, 192.168.1.10:8000, 127.0.0.1:8000, etc.)

No, non puoi avere due applicazioni in ascolto sullo stesso "indirizzo TCP", perché quando arriva un messaggio, come fa il kernel a sapere a quale applicazione dare il messaggio?

Tuttavia, nella maggior parte dei sistemi operativi è possibile impostare più indirizzi IP su una singola interfaccia (ad esempio, se si dispone 192.168.1.10su un'interfaccia, è anche possibile impostare 192.168.1.11, se nessun altro sulla rete lo sta utilizzando), e in quei casi è possibile potrebbe avere applicazioni separate in ascolto sulla porta 8000su ciascuno di questi due indirizzi IP.


2

Se almeno uno degli IP remoti è già noto, statico e dedicato a parlare solo con una delle tue app, puoi utilizzare la regola iptables (table nat, chain PREROUTING) per reindirizzare il traffico in ingresso da questo indirizzo alla porta locale "condivisa" a qualsiasi altra porta in cui l'applicazione appropriata ascolti effettivamente.


1

Sì e no. Solo un'applicazione può ascoltare attivamente su una porta. Ma quell'applicazione può lasciare in eredità la sua connessione ad un altro processo. Quindi potresti avere più processi che lavorano sulla stessa porta.


@trusktr, penso che intendesse questo
warvariuc il


0

Se per applicazioni intendi più processi allora sì ma generalmente NO. Ad esempio, il server Apache esegue più processi sulla stessa porta (generalmente 80). Viene designato uno dei processi per collegarsi effettivamente alla porta e quindi utilizzare quel processo per eseguire passaggi ai vari processi che accettano connessioni.


0

È possibile fare in modo che due applicazioni ascoltino la stessa porta sulla stessa interfaccia di rete.

Può esserci un solo socket di ascolto per l'interfaccia e la porta di rete specificate, ma quel socket può essere condiviso tra più applicazioni.

Se hai un socket in ascolto in un processo applicativo e tu forkquel processo, il socket sarà ereditato, quindi tecnicamente ora ci saranno due processi in ascolto sulla stessa porta.


0

Ho provato quanto segue, con socat:

socat TCP-L:8080,fork,reuseaddr -

E anche se non ho effettuato una connessione al socket, non posso ascoltare due volte sulla stessa porta, nonostante l' reuseaddropzione.

Ricevo questo messaggio (che mi aspettavo prima):

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

0

Giusto per condividere ciò che ha detto @jnewton. Ho avviato un processo nginx e un tomcat incorporato sul mio mac. Riesco a vedere entrambi i processi in esecuzione a 8080.

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

-2

Risposta breve:

Seguendo la risposta fornita qui . Puoi avere due applicazioni in ascolto sullo stesso indirizzo IP e sullo stesso numero di porta, così a lungo una delle porte è una porta UDP, mentre l'altra è una porta TCP.

Spiegazione:

Il concetto di porta è rilevante sul livello di trasporto dello stack TCP / IP, quindi finché si utilizzano protocolli di livello di trasporto diversi dello stack, è possibile avere più processi in ascolto sulla stessa <ip-address>:<port>combinazione.

Un dubbio che le persone hanno è se due applicazioni sono in esecuzione sulla stessa <ip-address>:<port>combinazione, come farà un client in esecuzione su una macchina remota a distinguere le due? Se guardi l'intestazione del pacchetto del livello IP ( https://en.wikipedia.org/wiki/IPv4#Header ), vedrai che i bit da 72 a 79 sono usati per definire il protocollo, ecco come si può fare la distinzione.

Se comunque vuoi avere due applicazioni sulla stessa <ip-address>:<port>combinazione TCP , allora la risposta è no (Un esercizio interessante sarà lanciare due VM, dare loro lo stesso indirizzo IP, ma indirizzi MAC diversi e vedere cosa succede - noterai che alcune volte VM1 riceverà i pacchetti e altre volte VM2 riceverà i pacchetti, a seconda dell'aggiornamento della cache ARP).

Sento che facendo funzionare due applicazioni sullo stesso <op-address>:<port>vuoi ottenere un qualche tipo di bilanciamento del carico. Per questo è possibile eseguire le applicazioni su porte diverse e scrivere regole di tabella IP per dividere il traffico tra di esse.

Vedi anche la risposta di @ user6169806.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.