Могут ли два приложения прослушивать один и тот же порт?

могут ли два приложения на одной машине привязываться к одному порту и IP-адресу? Более того, приложение можно слушать запросы с определенного IP, а другой на другой удаленный IP? Я знаю, что могу иметь одно приложение, которое запускает два потока (или вилки), чтобы иметь подобное поведение, но могут ли два приложения, которые не имеют ничего общего, делать то же самое?

16 ответов


для TCP, нет. Вы можете одновременно прослушивать только одно приложение на одном порту. Теперь, если у вас есть 2 сетевые карты, вы можете прослушивать одно приложение на первом IP и втором IP, используя тот же номер порта.

для UDP (мультикаст), несколько приложений могут подписаться на один и тот же порт.


Да (для TCP) вы можете иметь две программы прослушивания на одном сокете, если программы предназначены для этого. Когда сокет создается первой программой, убедитесь, что SO_REUSEADDR опция установлена на сокете перед вами bind(). Однако это может быть не то, чего вы хотите. Это означает, что входящее TCP-соединение будет направлено на один программ, а не обоих, поэтому он не дублирует соединение, он просто позволяет двум программам обслуживать входящий запрос. Для например, веб-серверы будут иметь несколько процессов, прослушивающих порт 80, и O / S отправляет новое соединение процессу, который готов принять новые соединения.

SO_REUSEADDR

другие розетки bind() к этому порту, если нет активного слушающего сокета, привязанного к порту уже. Это позволяет обойти сообщения об ошибках "адрес уже используется" при попытке перезапустить сервер после сбоя.


в принципе, нет.

Это не написано на камне; но так пишутся все API: приложение открывает порт, получает к нему дескриптор, и ОС уведомляет его (через этот дескриптор), когда клиентское соединение (или пакет в случае UDP) прибывает.

Если ОС разрешила двум приложениям открывать один и тот же порт, как она узнает, какой из них уведомить?

но... есть способы обойти это:

  1. Как Джед отметить, вы могли бы написать "мастер" процесс, который был бы единственным, который действительно слушает порт и уведомляет других, используя любую логику, которую он хочет разделить запросы клиента.
    • в Linux и BSD (по крайней мере) вы можете настроить правила "переназначения", которые перенаправляют пакеты с "видимого" порта на другие (где приложения прослушивают), в соответствии с любыми сетевыми критериями (возможно, сеть происхождения или некоторые простые формы балансировки нагрузки).

Да.

  1. несколько прослушивающих TCP-сокетов, привязанных к одному порту, могут сосуществовать при условии, что все они привязаны к различным локальным IP-адресам. Клиенты могут подключаться к любому из них. Это исключает 0.0.0.0 (INADDR_ANY).

  2. несколько принят гнезда могут сосуществовать, все принятые от такого же слушая гнезда, все показывая такой же местный номер порта как слушать разъем.

  3. несколько сокетов UDP, связанных с одним и тем же портом, могут сосуществовать при условии, что либо то же условие, что и в (1), либо все они имели SO_REUSEADDR опция, установленная перед привязкой.

  4. TCP-порты и UDP-порты занимают разные пространства имен, поэтому использование порта для TCP не исключает его использования для UDP и наоборот.

Ссылка: Стивенс И Райт,TCP / IP иллюстрированный, Том II.


нет. Только одно приложение может привязываться к порту одновременно, и поведение, если привязка принудительная, неопределенно.

с многоадресными сокетами - которые звучат как нигде рядом с тем, что вы хотите-более одного приложения может привязываться к порту, пока SO_REUSEADDR установлен в параметрах каждого сокета.

вы можете выполнить это, написав процесс "master", который принимает и обрабатывает все соединения, а затем передает их вашим двум приложениям, которым нужно слушать тот же порт. Это подход, который веб-серверы и такие принимают, так как многие процессы должны слушать 80.

помимо этого, мы переходим к деталям - вы отметили как TCP, так и UDP, что это? Кроме того, какая платформа?


Да, Конечно. Насколько я помню, начиная с версии ядра 3.9 (не уверен в версии), поддержка . SO_RESUEPORT позволяет привязку к тому же порту и адресу, если первый сервер устанавливает этот параметр перед привязкой сокета.

это работает для обоих TCP и UDP. Более подробную информацию см. по ссылке:SO_REUSEPORT

Примечание: принято отвечать больше не соответствует моему мнению.


вы можете иметь одно приложение на один порт для одного сетевого интерфейса. Поэтому вы могли бы:

  1. httpd прослушивание на удаленно доступном интерфейсе, например 192.168.1.1:80
  2. еще один демон прослушивает 127.0.0.1:80

пример использования может быть использование httpd Как балансировщик нагрузки или прокси.


другой способ-использовать прослушивание программы в одном порту, который анализирует вид трафика (ssh, https и т. д.), который он перенаправляет внутренне на другой порт, на котором прослушивается "реальная" служба.

например, для Linux, sslh: https://github.com/yrutschle/sslh


Если хотя бы один из удаленных IPs уже известен, статичен и предназначен для разговора только с одним из ваших приложений, вы можете использовать правило iptables (таблица nat, цепная предварительная маршрутизация) для перенаправления трафика с этого адреса на "общий" локальный порт на любой другой порт, где соответствующее приложение действительно прослушивает.


да и нет. Только одно приложение может активно прослушивать порт. Но это приложение может завещать свою связь с другим процессом. Таким образом, вы можете иметь несколько процессов, работающих на одном порту.


да.

из этой статьи:
https://lwn.net/Articles/542629/

новая опция сокета позволяет нескольким сокетам на одном хосте привязываться к одному порту


когда вы создаете TCP-соединение, вы просите подключиться к определенному TCP-адресу, который представляет собой комбинацию IP-адреса (v4 или v6, в зависимости от используемого протокола) и порта.

когда сервер прослушивает соединения, он может сообщить ядру, что он хотел бы прослушивать определенный IP-адрес и порт, т. е. один IP-адрес, или на всех IP-адресах хостов, каждый на определенном порту, который эффективно прослушивает много разных "TCP-адресов" (например,, 192.168.1.10:8000, 127.0.0.1:8000 и др.)

нет, у вас не может быть двух приложений, прослушивающих один и тот же" TCP-адрес", потому что, когда приходит сообщение, как ядро узнает, какому приложению передать сообщение?

однако в большинстве операционных систем вы можете настроить несколько IP-адресов на одном интерфейсе (например, если у вас есть 192.168.1.10 на интерфейсе, вы также можете настроить 192.168.1.11, если никто другой в сети не использует его), и в этих случаях вы может иметь отдельные приложения, прослушивающие порт 8000 на каждом из этих двух IP-адресов.


Если под приложениями вы подразумеваете несколько процессов, то да, но обычно нет. Например, Apache server запускает несколько процессов на одном порту (обычно 80).Это делается путем назначения одного из процессов для фактической привязки к порту, а затем использовать этот процесс для передачи различных процессов, которые принимают соединения.


можно сделать два приложения, прослушивать один и тот же порт на одном сетевом интерфейсе.

для указанного сетевого интерфейса и порта может быть только один прослушивающий сокет,но этот сокет может использоваться несколькими приложениями.

Если у вас есть прослушивающий сокет в процессе приложения, и вы fork этот процесс, сокет будет унаследован, поэтому технически теперь будет два процесса, слушающих один и тот же порт.


я попробовал следующее, С socat:

socat TCP-L:8080,fork,reuseaddr -

и хотя я не подключился к сокету, я не могу прослушивать дважды один и тот же порт, несмотря на .

Я получаю это сообщение (которое я и предполагал ранее):

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

короткий ответ:

идем на ответ здесь. У вас может быть два приложения, прослушивающие один и тот же IP-адрес и номер порта, так что один из портов является UDP-портом, а другой-TCP-портом.

пояснение:

концепция порта уместна на транспортном уровне стека TCP/IP, таким образом, пока вы используете различные протоколы транспортного уровня стека, вы можете иметь несколько процессы прослушивания на одном и том же <ip-address>:<port> комбинации.

одно сомнение, что люди есть, если два приложения работают на одном и том же <ip-address>:<port> комбинация, как клиент, работающий на удаленной машине, различает их? Если вы посмотрите на заголовок пакета IP-уровня (https://en.wikipedia.org/wiki/IPv4#Header), вы увидите, что биты 72 до 79 используются для определения протокола, вот как можно сделать различие.

однако, если вы хотите иметь два приложения на одном TCP <ip-address>:<port> комбинация, тогда ответ нет (интересным упражнением будет запуск двух виртуальных машин, дайте им один и тот же IP - адрес, но разные MAC - адреса, и посмотрите, что произойдет-вы заметите, что в некоторых случаях VM1 получит пакеты, а в других случаях VM2 получит пакеты-в зависимости от обновления кэша ARP).

Я чувствую, что, заставляя два приложения работать на одном и том же <op-address>:<port> вы хотите достичь какой-то балансировки нагрузки. Для этого вы можете запускать приложения на различные порты, и написать правила таблицы IP для разделения трафика между ними.

Также см. ответ @user6169806.