¿Pueden dos aplicaciones escuchar el mismo puerto?

283

¿Pueden dos aplicaciones en la misma máquina unirse al mismo puerto y dirección IP? Yendo un paso más allá, ¿puede una aplicación escuchar solicitudes provenientes de una determinada IP y la otra a otra IP remota? Sé que puedo tener una aplicación que comience dos hilos (o bifurcaciones) para tener un comportamiento similar, pero ¿pueden dos aplicaciones que no tienen nada en común hacer lo mismo?

nadiv
fuente
2
Para una buena respuesta detallada sobre la reutilización de direcciones / puertos con múltiples sockets: stackoverflow.com/questions/14388706/…
Bjarke Freund-Hansen

Respuestas:

248

La respuesta difiere según qué sistema operativo se esté considerando. En general, sin embargo:

Para TCP, no. Solo puede tener una aplicación escuchando en el mismo puerto a la vez. Ahora, si tuviera 2 tarjetas de red, podría hacer que una aplicación escuche en la primera IP y la segunda en la segunda IP usando el mismo número de puerto.

Para UDP (Multicasts), varias aplicaciones pueden suscribirse al mismo puerto.

Editar: desde Linux Kernel 3.9 y posterior, se agregó soporte para múltiples aplicaciones que escuchan el mismo puerto usando la SO_REUSEPORTopción. Más información está disponible en este artículo de lwn.net.

Chris Dail
fuente
22
"una aplicación que escucha en un solo puerto" es la razón por la que existen puertos: para permitir que múltiples aplicaciones compartan la red sin conflictos.
S.Lott
46
Un oyente por puerto por dirección IP. Agregar otra interfaz de red es una forma de obtener una segunda dirección IP. Es probable que su plataforma admita interfaces virtuales, que es otra forma de obtener dos direcciones IP con una tarjeta de red física.
John M
77
Aunque tenía la misma opinión hasta ahora, ¡resultó que pude vincular dos procesos diferentes al mismo puerto ip y TCP! Esto es posible si configura ServerSocket.setReuseAddress (true) en Java antes de enlazarlo. Comportamiento realmente inesperado.
Eugen
77
(1) El significado real de su respuesta es 'Para TCP, sí, siempre que ...' (2) La multidifusión no es una condición previa para compartir el puerto UDP, pero SO_REUSEADDR sí lo es.
Marqués de Lorne
12
Para UDP (Multicasts), varias aplicaciones pueden suscribirse al mismo puerto. Si un paquete ha llegado del cliente, ¿qué aplicación lo recibe?
Yang Juven
123

Sí (para TCP) puede hacer que dos programas escuchen en el mismo socket, si los programas están diseñados para hacerlo. Cuando el primer programa crea el socket, asegúrese de que la SO_REUSEADDRopción esté configurada en el socket antes que usted bind(). Sin embargo, esto puede no ser lo que quieres. Lo que esto hace es que una conexión TCP entrante se dirigirá a uno de los programas, no a ambos, por lo que no duplica la conexión, solo permite que dos programas atiendan la solicitud entrante. Por ejemplo, los servidores web tendrán múltiples procesos, todos escuchando en el puerto 80, y el O / S envía una nueva conexión al proceso que está lista para aceptar nuevas conexiones.

SO_REUSEADDR

Permite otros zócalos a bind()este puerto, a menos que ya haya un zócalo de escucha activo vinculado al puerto. Esto le permite evitar los mensajes de error "Dirección ya en uso" cuando intenta reiniciar su servidor después de un bloqueo.

JNewton
fuente
1
TCP + UDP ahora funciona (dado un núcleo lo suficientemente nuevo). Vea el enlace que agregué a la respuesta.
dpb
3
Esta respuesta no es correcta a menos que todos los sockets estén vinculados a distintas direcciones IP, ninguna de las cuales es INADDR_ANY, o a menos que esté en Windows, donde el resultado no está definido.
Marqués de Lorne
1
¿Puede ampliar cómo van los datos a una aplicación específica en el mismo puerto? ¿Hay alguna preocupación de seguridad en la que pensar cuando las aplicaciones usan SO_REUSEADDR o SO_REUSEPORT?
trusktr
@EJP ¿Puedes echar un vistazo a mi comentario anterior?
trusktr
3
SO_REUSEADDRciertamente no le permite tener dos sockets TCP en estado de escucha al mismo tiempo, al menos en Unix. Está destinado a moverse por TIME_WAIT state: unixguide.net/network/socketfaq/4.5.shtml . Puede funcionar en Windows, pero no está garantizado que la solicitud llegue al servidor correcto de todos modos).
Bruno
48

Si.

  1. Pueden coexistir múltiples sockets TCP de escucha, todos vinculados al mismo puerto, siempre que estén vinculados a diferentes direcciones IP locales. Los clientes pueden conectarse a la que necesiten. Esto excluye 0.0.0.0( INADDR_ANY).

  2. Pueden existir múltiples sockets aceptados , todos aceptados desde el mismo socket de escucha, todos mostrando el mismo número de puerto local que el socket de escucha.

  3. Múltiples zócalos UDP, todos vinculados al mismo puerto, pueden coexistir siempre que se cumpla la misma condición que en (1) o todos hayan establecido la SO_REUSEADDRopción antes del enlace.

  4. Los puertos TCP y los puertos UDP ocupan espacios de nombres diferentes, por lo que el uso de un puerto para TCP no impide su uso para UDP, y viceversa.

Referencia: Stevens & Wright, TCP / IP Ilustrado, Volumen II.

Marqués de Lorne
fuente
¿Tienes un enlace a mano? La oportunidad de la coexistencia de TCP-UDP es mi pregunta. Gracias de antemano :)
Wolf
1
@ Wolf Solo inténtalo. Esa es toda la prueba que realmente necesitas. Mi cita es Stevens & Wright: no puedes ser mucho mejor que eso.
Marqués de Lorne
1
Gracias por la respuesta, necesito leer aún más atento. Ya escribió que UDP y TCP pueden coexistir .
Wolf
47

En principio, no.

No está escrito en piedra; pero es la forma en que se escriben todas las API: la aplicación abre un puerto, obtiene un identificador y el sistema operativo lo notifica (a través de ese identificador) cuando llega una conexión de cliente (o un paquete en caso UDP).

Si el sistema operativo permitiera que dos aplicaciones abrieran el mismo puerto, ¿cómo sabría cuál notificar?

Pero ... hay formas de evitarlo:

  1. Como señaló Jed , podría escribir un proceso 'maestro', que sería el único que realmente escucha en el puerto y notifica a los demás, utilizando cualquier lógica que quiera separar las solicitudes de los clientes.
    • En Linux y BSD (al menos) puede configurar reglas de 'reasignación' que redirigen los paquetes desde el puerto 'visible' a diferentes (donde las aplicaciones están escuchando), de acuerdo con cualquier criterio relacionado con la red (tal vez la red de origen, o algunos formas simples de equilibrio de carga).
Javier
fuente
37
iptables -m statistic --mode random --probability 0.5es divertido.
Jed Smith, el
1
¿Qué significa exactamente "Abre un puerto"? Entiendo la oración, pero ¿sabes qué hace exactamente el sistema cuando abre un puerto y lo maneja? Sé que cuando quieres abrir un puerto con TCP, obtienes una transmisión y esa transmisión es tu conexión con el control remoto, pero busco en la web y no encuentro una muy buena explicación.
Samuel
44
@Samuel: abrir un puerto (en modo servidor) significa obtener un descriptor de archivo, y cuando el sistema obtiene un paquete SYN para ese número de puerto, responde con SYN + ACK y genera un evento en el descriptor de archivo asociado. la aplicación responde a ese evento con una llamada accept (), que crea un nuevo descriptor de archivo asociado a la secuencia específica, dejando libre al descriptor del servidor original para obtener nuevas conexiones de los clientes
Javier
77
Esta respuesta no puede considerarse correcta. Pasa por alto por completo la existencia de SO_REUSEADDR y SO_REUSEPORT.
Marqués de Lorne
@Javier No, no lo hace. La apertura de un puerto desde el punto de vista de la aplicación del servidor ocurre cuando vincula el socket de escucha, o más bien vincula el socket que está a punto de listen()conectar. Lo más probable es que la pregunta sea sobre abrirlo en el firewall. Demasiados errores aquí, y todos sin corregir en 7 años. La respuesta también omite el caso de enlace a diferentes direcciones locales con el mismo número de puerto. De hecho, es totalmente incorrecto.
Marqués de Lorne
27

Si definitivamente . Por lo que recuerdo, desde la versión 3.9 del kernel (no estoy seguro de la versión) SO_REUSEPORTse introdujo el soporte para . SO_RESUEPORTpermite vincular exactamente al mismo puerto y dirección, siempre que el primer servidor configure esta opción antes de vincular su socket.

Funciona tanto para TCP como para UDP . Consulte el enlace para más detalles: SO_REUSEPORT

Nota : La respuesta aceptada ya no es válida según mi opinión.

piyush
fuente
2
Totalmente cierto. Si no fuera cierto, ¿cómo podría funcionar Wireshark?
Staszek
55
@Staszek Wireshark no escucha los puertos. Funciona a nivel de paquete.
Marqués de Lorne
Oh, eso tendría sentido. De todos modos, escuchar dos puertos por 2 aplicaciones seguramente es posible.
Staszek
18

No. Solo una aplicación puede enlazarse a un puerto a la vez, y el comportamiento si el enlace es forzado es indeterminado.

Con sockets de multidifusión, que no parecen estar cerca de lo que desea, más de una aplicación puede vincularse a un puerto siempre que SO_REUSEADDR esté configurado en las opciones de cada socket.

Puede lograr esto escribiendo un proceso "maestro", que acepte y procese todas las conexiones, luego las entregue a sus dos aplicaciones que necesitan escuchar en el mismo puerto. Este es el enfoque que adoptan los servidores web y similares, ya que muchos procesos necesitan escuchar 80.

Más allá de esto, estamos entrando en detalles: etiquetó tanto TCP como UDP, ¿cuál es? Además, ¿qué plataforma?

Jed Smith
fuente
ambos son de mi interés. La plataforma es Windows, pero si la respuesta es diferente para Linux, sería bueno saberlo
nadiv el
8
No existe tal cosa como un socket de multidifusión. Hay sockets UDP. La multidifusión no es una condición previa para SO_REUSEADDR.
Marqués de Lorne
3

Puede tener una aplicación escuchando en un puerto para una interfaz de red. Por lo tanto, podrías tener:

  1. httpd escuchando en una interfaz accesible remotamente, p. ej. 192.168.1.1:80
  2. otro demonio escuchando 127.0.0.1:80

Un caso de uso de muestra podría ser usar httpdcomo equilibrador de carga o proxy.

Tomás Tomecek
fuente
3

Otra forma es usar un programa que escucha en un puerto que analiza el tipo de tráfico (ssh, https, etc.) que redirige internamente a otro puerto en el que escucha el servicio "real".

Por ejemplo, para Linux, sslh: https://github.com/yrutschle/sslh

Mitchbcn
fuente
¿Existe tal programa en Windows? Necesito que tanto mi servidor IIS local como el agente ActiveMQ escuchen en el puerto 443
Harvey Lin
3

Cuando crea una conexión TCP, solicita conectarse a una dirección TCP específica, que es una combinación de una dirección IP (v4 o v6, dependiendo del protocolo que esté usando) y un puerto.

Cuando un servidor escucha las conexiones, puede informar al kernel que le gustaría escuchar una dirección IP y un puerto específicos, es decir, una dirección TCP, o en el mismo puerto en cada una de las direcciones IP del host (generalmente especificado con la dirección IP 0.0.0.0), que está a la escucha de manera efectiva en una gran cantidad de diferentes direcciones TCP "" (por ejemplo, 192.168.1.10:8000, 127.0.0.1:8000, etc.)

No, no puede tener dos aplicaciones escuchando en la misma "dirección TCP", porque cuando llega un mensaje, ¿cómo sabría el núcleo a qué aplicación entregar el mensaje?

Sin embargo, en la mayoría de los sistemas operativos puede configurar varias direcciones IP en una sola interfaz (por ejemplo, si tiene 192.168.1.10una interfaz, también puede configurarla 192.168.1.11, si nadie más en la red la está usando), y en esos casos usted podría tener aplicaciones separadas escuchando en el puerto 8000en cada una de esas dos direcciones IP.

cjs
fuente
2

Si al menos una de las IP remotas ya es conocida, estática y dedicada a hablar solo con una de sus aplicaciones, puede usar la regla de iptables (tabla nat, PREROUTING en cadena) para redirigir el tráfico entrante de esta dirección al puerto local "compartido" a cualquier otro puerto donde realmente escuche la aplicación apropiada.

Stemar
fuente
1

Si y no. Solo una aplicación puede escuchar activamente en un puerto. Pero esa aplicación puede dejar su conexión a otro proceso. Entonces podría tener múltiples procesos trabajando en el mismo puerto.

rajesh
fuente
@trusktr, creo que se refería a esto
warvariuc
1

Si.

De este artículo:
https://lwn.net/Articles/542629/

La nueva opción de socket permite que múltiples sockets en el mismo host se unan al mismo puerto

usuario6169806
fuente
1
Buen enlace, sin embargo, no escriba esta línea allí - La opción SO_REUSEPORT no es estándar
Sahil Singh
0

Si por aplicaciones te refieres a múltiples procesos, sí, pero generalmente NO. Por ejemplo, el servidor Apache ejecuta múltiples procesos en el mismo puerto (generalmente 80). Se hace mediante la designación de uno de los procesos para que realmente se una al puerto y luego use ese proceso para realizar transferencias a varios procesos que aceptan conexiones.

nitinsh99
fuente
0

Puede hacer que dos aplicaciones escuchen el mismo puerto en la misma interfaz de red.

Solo puede haber un socket de escucha para la interfaz de red y el puerto especificados, pero ese socket se puede compartir entre varias aplicaciones.

Si tiene un socket de escucha en un proceso de aplicación y forkese proceso, el socket se heredará, por lo que técnicamente ahora habrá dos procesos escuchando el mismo puerto.

warvariuc
fuente
0

He intentado lo siguiente, con socat:

socat TCP-L:8080,fork,reuseaddr -

Y aunque no he realizado una conexión al socket, no puedo escuchar dos veces en el mismo puerto, a pesar de la reuseaddropción.

Recibo este mensaje (que esperaba antes):

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

Solo para compartir lo que @jnewton mencionó. Comencé un nginx y un proceso de tomcat incrustado en mi mac. Puedo ver que ambos procesos se ejecutan en 8080.

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

Respuesta corta:

Yendo por la respuesta dada aquí . Puede tener dos aplicaciones escuchando en la misma dirección IP y número de puerto, siempre que uno de ellos sea un puerto UDP, mientras que otro sea un puerto TCP.

Explicación:

El concepto de puerto es relevante en la capa de transporte de la pila TCP / IP, por lo tanto, siempre que utilice diferentes protocolos de la capa de transporte de la pila, puede tener múltiples procesos escuchando en la misma <ip-address>:<port>combinación.

Una duda que la gente tiene es que si dos aplicaciones se ejecutan en la misma <ip-address>:<port>combinación, ¿cómo distinguirá un cliente que se ejecuta en una máquina remota entre las dos? Si observa el encabezado del paquete de la capa IP ( https://en.wikipedia.org/wiki/IPv4#Header ), verá que los bits 72 a 79 se utilizan para definir el protocolo, así es como se puede hacer la distinción.

Sin embargo, si desea tener dos aplicaciones en la misma <ip-address>:<port>combinación de TCP , entonces la respuesta es no (un ejercicio interesante será lanzar dos máquinas virtuales, darles la misma dirección IP, pero diferentes direcciones MAC, y ver qué sucede; notará que algunas veces VM1 obtendrá paquetes, y otras veces VM2 obtendrá paquetes, dependiendo de la actualización de caché ARP).

Creo que al hacer que dos aplicaciones se ejecuten en la misma <op-address>:<port>, desea lograr algún tipo de equilibrio de carga. Para esto, puede ejecutar las aplicaciones en diferentes puertos y escribir reglas de tabla IP para bifurcar el tráfico entre ellas.

Ver también la respuesta de @ user6169806.

Sahil Singh
fuente