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

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

Ответ 1

Ответ зависит от того, какая ОС рассматривается. В общем, хотя:

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

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

Изменение: Начиная с Linux Kernel 3.9 и более поздних версий, поддержка нескольких приложений, прослушивающих один и тот же порт, была добавлена с использованием опции SO_REUSEPORT. Более подробная информация доступна на этой статье lwn.net.

Ответ 2

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

SO_REUSEADDR

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

Ответ 3

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

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

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

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

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

Ответ 4

Да.

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

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

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

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

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

Ответ 5

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

Он работает как для TCP, так и UDP. Для получения дополнительной информации см. Ссылку: SO_REUSEPORT

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

Ответ 6

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

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

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

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

Ответ 7

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

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

Ответ 8

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

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

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

Ответ 9

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

Ответ 10

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

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

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

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

Ответ 11

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

Ответ 12

Да.

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

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

Ответ 13

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

Ответ 14

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

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

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

Ответ 15

Я пробовал следующее: socat:

socat TCP-L:8080,fork,reuseaddr -

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

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

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

Ответ 16

Просто чтобы поделиться тем, что упомянул @jnewton. Я запустил nginx и встроенный процесс tomcat на моем Mac. Я вижу, как процесс запускается на 8080.

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

Ответ 17

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

Идем по ответу здесь. Вы можете прослушивать два приложения на одном 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.