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


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

16 223

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 и наоборот.

Ссылка: Stevens & Wright,TCP/IP иллюстрированный, Том II.

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

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

вы можете сделать это, написав "мастер" процесс, который принимает и обрабатывает все соединения, а затем передает их в ваши два приложения, которые должны слушать дальше тот же порт. Это подход, который веб-серверы и такие принимают, так как многие процессы должны слушать 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

Если хотя бы один из удаленных IP-адресов уже известен, статичен и предназначен для разговора только с одним из ваших приложений, вы можете использовать правило 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 запускает несколько процессов на одном порту (как правило, 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.