Dois aplicativos podem ouvir a mesma porta?


283

Dois aplicativos na mesma máquina podem se vincular à mesma porta e endereço IP? Indo um passo adiante, um aplicativo pode ouvir solicitações provenientes de um determinado IP e o outro para outro IP remoto? Sei que posso ter um aplicativo que inicia dois threads (ou bifurcações) para ter um comportamento semelhante, mas dois aplicativos que não têm nada em comum podem fazer o mesmo?


2
Para uma boa resposta detalhada sobre a reutilização de endereços / portas com vários soquetes: stackoverflow.com/questions/14388706/…
Bjarke Freund-Hansen

Respostas:


248

A resposta varia de acordo com o SO que está sendo considerado. Em geral, porém:

Para TCP, não. Você pode ter apenas um aplicativo escutando na mesma porta ao mesmo tempo. Agora, se você tivesse duas placas de rede, um aplicativo poderia escutar no primeiro IP e o segundo no segundo IP usando o mesmo número de porta.

Para UDP (Multicasts), vários aplicativos podem se inscrever na mesma porta.

Edit: Desde o Linux Kernel 3.9 e posterior, o suporte para vários aplicativos que ouvem a mesma porta foi adicionado usando a SO_REUSEPORTopção Mais informações estão disponíveis neste artigo da lwn.net.


22
"um aplicativo escutando em uma única porta", é por isso que existem portas - para permitir que vários aplicativos compartilhem a rede sem conflitos.
7409 S.Lott

46
Um ouvinte por porta por endereço IP. Adicionar outra interface de rede é uma maneira de obter um segundo endereço IP. Sua plataforma provavelmente suporta interfaces virtuais, que é outra maneira de obter dois endereços IP com uma placa de rede física.
John M

7
Embora eu tivesse a mesma opinião até agora, eu consegui ligar dois processos diferentes à mesma porta IP e TCP! Isso é possível se você configurar ServerSocket.setReuseAddress (true) em Java antes de vincular a ele. Comportamento realmente inesperado.
Eugen

7
(1) O significado real da sua resposta é 'Para TCP, sim, desde ...' (2) Multicast não é uma condição prévia para o compartilhamento de porta UDP, mas SO_REUSEADDR.
Marquês de Lorne

12
Para UDP (Multicasts), vários aplicativos podem se inscrever na mesma porta. Se um pacote chegou do cliente, qual aplicativo o recebeu?
Yang Juven

123

Sim (para TCP), você pode ter dois programas ouvindo no mesmo soquete, se os programas forem projetados para isso. Quando o soquete é criado pelo primeiro programa, verifique se a SO_REUSEADDRopção está definida no soquete antes de você bind(). No entanto, isso pode não ser o que você deseja. O que isso faz é que uma conexão TCP de entrada seja direcionada a um dos programas, não a ambos, para que não duplique a conexão, apenas permite que dois programas atendam à solicitação de entrada. Por exemplo, os servidores da Web terão vários processos, todos escutando na porta 80, e o O / S envia uma nova conexão ao processo, pronta para aceitar novas conexões.

SO_REUSEADDR

Permite outros soquetes bind()nessa porta, a menos que já exista um soquete de escuta ativo vinculado à porta. Isso permite que você contorne as mensagens de erro "Endereço já em uso" ao tentar reiniciar o servidor após uma falha.


1
O TCP + UDP agora funciona (dado um kernel novo o suficiente). Veja o link que adicionei à resposta.
Dpb 29/04

3
Esta resposta não está correta, a menos que todos os soquetes estejam vinculados a endereços IP distintos, nenhum dos quais é INADDR_ANY ou a menos que você esteja no Windows, onde o resultado é indefinido.
Marquês de Lorne

1
Você pode expandir como os dados vão para um aplicativo específico na mesma porta? Há alguma preocupação de segurança em que pensar quando os aplicativos usam SO_REUSEADDR ou SO_REUSEPORT?
trusktr

@EJP Você também pode dar uma olhada no meu comentário anterior?
trusktr

3
SO_REUSEADDRcertamente não permite que você tenha dois soquetes TCP no estado de escuta ao mesmo tempo, pelo menos no Unix. Ele serve para contornar o TIME_WAIT state: unixguide.net/network/socketfaq/4.5.shtml . Pode funcionar no Windows, mas você não tem garantia de que a solicitação chegará ao servidor certo de qualquer maneira).
1155 Bruno

48

Sim.

  1. Vários soquetes TCP de escuta, todos vinculados à mesma porta, podem coexistir, desde que estejam vinculados a diferentes endereços IP locais. Os clientes podem se conectar a qualquer um que precisarem. Isso exclui 0.0.0.0( INADDR_ANY).

  2. Vários soquetes aceitos podem coexistir, todos aceitos no mesmo soquete de escuta, mostrando o mesmo número de porta local que o soquete de escuta.

  3. Vários soquetes UDP, todos ligados à mesma porta, podem coexistir, desde a mesma condição que em (1) ou todos tiveram a SO_REUSEADDRopção definida antes da ligação.

  4. As portas TCP e UDP ocupam espaços de nomes diferentes, portanto, o uso de uma porta para TCP não impede seu uso para UDP e vice-versa.

Referência: Stevens & Wright, TCP / IP ilustrado, volume II.


você tem um link em mãos? A oportunidade de coexistência de TCP-UDP é minha própria pergunta. Agradecemos antecipadamente :)
Lobo

1
@ Wolf Basta tentar. Essa é toda a prova de que você realmente precisa. Minha citação é Stevens & Wright: você não pode ficar muito melhor que isso.
Marquês de Lorne

1
Obrigado pela resposta, preciso ler ainda mais atentamente. Você já escreveu que UDP e TCP podem coexistir .
Wolf

47

Em princípio, não.

Não está escrito em pedra; mas é assim que todas as APIs são escritas: o aplicativo abre uma porta, identifica-o e o sistema operacional o notifica (por esse identificador) quando uma conexão de cliente (ou um pacote no caso de UDP) chega.

Se o sistema operacional permitisse que dois aplicativos abrissem a mesma porta, como saberia qual deles notificar?

Mas ... existem maneiras de contornar isso:

  1. Como Jed observou , você pode escrever um processo 'mestre', que seria o único que realmente escuta na porta e notifica outras pessoas, usando qualquer lógica que deseje separar solicitações de clientes.
    • No Linux e no BSD (pelo menos), você pode configurar regras de 'remapeamento' que redirecionam pacotes da porta 'visível' para diferentes (onde os aplicativos estão ouvindo), de acordo com qualquer critério relacionado à rede (talvez rede de origem ou algum formas simples de balanceamento de carga).

37
iptables -m statistic --mode random --probability 0.5é divertido.
Jed Smith

1
O que significa exatamente "Abre uma porta"? Entendo a frase, mas você sabe o que exatamente o sistema faz quando abre uma porta e lida com isso? Sei que quando você deseja abrir uma porta com TCP, obtém um fluxo e esse fluxo é a sua conexão com o controle remoto, mas pesquiso na web e não encontrei uma explicação muito boa.
Samuel

4
@ Samuel: abrir uma porta (no modo servidor) significa obter um descritor de arquivo e, quando o sistema obtém um pacote SYN para esse número de porta, responde com SYN + ACK e gera um evento no descritor de arquivo associado. o aplicativo responde a esse evento com uma chamada accept (), que cria um novo descritor de arquivo associado ao fluxo específico, deixando o descritor do servidor original livre para obter novas conexões dos clientes
Javier

7
Esta resposta não pode ser considerada correta. Ignora completamente a existência de SO_REUSEADDR e SO_REUSEPORT.
Marquês de Lorne

@Javier Não, não. A abertura de uma porta do ponto de vista do aplicativo do servidor ocorre quando você liga o soquete de escuta ou, em vez disso, o soquete em que está prestes a listen()ligar. Provavelmente, a pergunta é sobre como abri-lo no firewall. Muitos erros aqui e todos sem correção em 7 anos. A resposta também omite o caso de ligação a um endereço local diferente com o mesmo número de porta. Na verdade, é totalmente incorreto.
Marquês de Lorne

27

Sim definitivamente . Tanto quanto me lembro, a partir do kernel versão 3.9 (Não tenho certeza da versão), SO_REUSEPORTfoi apresentado o suporte para o . SO_RESUEPORTpermite a ligação exatamente à mesma porta e endereço, desde que o primeiro servidor defina essa opção antes de vincular seu soquete.

Funciona para TCP e UDP . Consulte o link para obter mais detalhes: SO_REUSEPORT

Nota : A resposta aceita não é mais verdadeira conforme minha opinião.


2
Completamente verdade. Se não fosse verdade, como o Wireshark poderia funcionar?
Staszek

5
@Staszek Wireshark não escuta portas. Opera no nível do pacote.
Marquês de Lorne

Oh, isso faria sentido. De qualquer forma, é possível ouvir duas portas por 2 aplicativos.
Staszek

18

Não. Somente um aplicativo pode ligar a uma porta por vez, e o comportamento se a ligação for forçada é indeterminado.

Com soquetes multicast - que parecem nem chegar perto do que você deseja - mais de um aplicativo pode se conectar a uma porta, desde que SO_REUSEADDR esteja definido nas opções de cada soquete.

Você pode fazer isso escrevendo um processo "mestre", que aceita e processa todas as conexões e as entrega aos seus dois aplicativos que precisam ouvir na mesma porta. Essa é a abordagem que os servidores da Web e outros adotam, já que muitos processos precisam ouvir 80.

Além disso, estamos entrando em detalhes - você marcou o TCP e o UDP, qual é? Além disso, qual plataforma?


ambos são do meu interesse. A plataforma é o Windows, mas se a resposta é diferente para Linux, seria bom saber
Nadiv

8
Não existe um soquete multicast. Existem soquetes UDP. O multicast não é uma condição prévia para SO_REUSEADDR.
Marquês de Lorne

3

Você pode ter um aplicativo escutando em uma porta uma interface de rede. Portanto, você pode ter:

  1. httpd ouvindo em uma interface remotamente acessível, por exemplo 192.168.1.1:80
  2. outro daemon ouvindo 127.0.0.1:80

O exemplo de caso de uso pode ser usado httpdcomo um balanceador de carga ou um proxy.


3

Outra maneira é usar um programa que escuta em uma porta que analisa o tipo de tráfego (ssh, https, etc) que redireciona internamente para outra porta na qual o serviço "real" está escutando.

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


Existe um programa desse tipo no Windows? Eu preciso ter tanto o meu servidor IIS local e ActiveMQ corretor de escutar na porta 443
Harvey Lin

3

Ao criar uma conexão TCP, você solicita a conexão com um endereço TCP específico, que é uma combinação de um endereço IP (v4 ou v6, dependendo do protocolo que você está usando) e uma porta.

Quando um servidor escuta conexões, ele pode informar ao kernel que gostaria de ouvir um endereço IP e uma porta específicos, ou seja, um endereço TCP ou na mesma porta em cada um dos endereços IP do host (geralmente especificado com o endereço IP). 0.0.0.0), que é efetivamente escutando um monte de diferentes "endereços TCP" (eg, 192.168.1.10:8000, 127.0.0.1:8000, etc.)

Não, você não pode ter dois aplicativos ouvindo o mesmo "endereço TCP", porque quando uma mensagem é exibida, como o kernel saberia para qual aplicativo enviar a mensagem?

No entanto, na maioria dos sistemas operacionais, você pode configurar vários endereços IP em uma única interface (por exemplo, se você tiver 192.168.1.10uma interface, também poderá configurar 192.168.1.11, se ninguém mais estiver na rede) e, nesses casos, poderia ter aplicativos separados escutando na porta 8000em cada um desses dois endereços IP.


2

Se pelo menos um dos IPs remotos já for conhecido, estático e dedicado para conversar apenas com um de seus aplicativos, você poderá usar a regra iptables (tabela nat, cadeia PREROUTING) para redirecionar o tráfego de entrada desse endereço para a porta local "compartilhada" para qualquer outra porta em que o aplicativo apropriado realmente escute.


1

Sim e não. Somente um aplicativo pode escutar ativamente em uma porta. Mas esse aplicativo pode deixar sua conexão com outro processo. Então você pode ter vários processos trabalhando na mesma porta.


@trusktr, eu acho que ele quis dizer isso
warvariuc


0

Se por aplicativos você quer dizer vários processos, então sim, mas geralmente NÃO. Por exemplo, o servidor Apache executa vários processos na mesma porta (geralmente 80). Isso é feito designando um dos processos para realmente se conectar à porta e, em seguida, use esse processo para fazer transferências para vários processos que estão aceitando conexões.


0

Você pode fazer dois aplicativos ouvirem a mesma porta na mesma interface de rede.

Só pode haver um soquete de escuta para a interface e a porta de rede especificadas, mas esse soquete pode ser compartilhado entre vários aplicativos.

Se você tiver um soquete de escuta em um processo de aplicativo e você forknesse processo, o soquete será herdado, então tecnicamente haverá agora dois processos escutando a mesma porta.


0

Eu tentei o seguinte, com socat:

socat TCP-L:8080,fork,reuseaddr -

E mesmo que eu não tenha feito uma conexão ao soquete, não consigo ouvir duas vezes na mesma porta, apesar da reuseaddropção.

Recebo esta mensagem (que eu esperava antes):

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

0

Apenas para compartilhar o que @jnewton mencionou. Comecei um processo nginx e tomcat incorporado no meu mac. Eu posso ver os dois processos em execução no 8080.

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

-2

Resposta curta:

Indo pela resposta dada aqui . Você pode ter dois aplicativos ouvindo no mesmo endereço IP e número da porta, desde que uma porta seja uma porta UDP, enquanto outra é uma porta TCP.

Explicação:

O conceito de porta é relevante na camada de transporte da pilha TCP / IP, portanto, enquanto você estiver usando diferentes protocolos da camada de transporte, poderá ter vários processos ouvindo a mesma <ip-address>:<port>combinação.

Uma dúvida que as pessoas têm é que, se dois aplicativos estiverem sendo executados na mesma <ip-address>:<port>combinação, como um cliente executando em uma máquina remota fará a distinção entre os dois? Se você observar o cabeçalho do pacote da camada IP ( https://en.wikipedia.org/wiki/IPv4#Header ), verá que os bits 72 a 79 são usados ​​para definir o protocolo, é assim que a distinção pode ser feita.

Se, no entanto, você quiser ter dois aplicativos na mesma <ip-address>:<port>combinação de TCP , a resposta é não (um exercício interessante será lançar duas VMs, fornecer o mesmo endereço IP, mas endereços MAC diferentes e ver o que acontece - você notará que algumas vezes A VM1 receberá pacotes e outras vezes a VM2 receberá pacotes - dependendo da atualização do cache do ARP).

Sinto que, ao fazer dois aplicativos serem executados da mesma maneira, <op-address>:<port>você deseja obter algum tipo de balanceamento de carga. Para isso, você pode executar os aplicativos em portas diferentes e escrever regras de tabela IP para bifurcar o tráfego entre elas.

Veja também a resposta de @ user6169806.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.