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

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

Для TCP нет. Одновременно можно прослушивать только одно приложение на одном и том же порту. Теперь, если у вас есть две сетевые карты, вы можете использовать одно приложение для первого 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 Illustrated, том II.

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

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

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

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

Да, конечно . Насколько я помню Начиная с версии ядра 3.9 (не уверен в версии), была введена поддержка SO_REUSEPORT . 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 (table nat, chain PREROUTING) для перенаправления входящего трафика с этого адреса на «общий» локальный порт на любой другой порт, в котором приложение действительно прослушивается.

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

Да.

Из этой статьи:
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-адрес», потому что, когда приходит сообщение, как kernel ​​узнает, какое приложение будет выдавать сообщение?

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

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

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

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

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

Я пробовал следующее, с 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 

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

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

Объяснение:

Концепция порта имеет отношение к транспортному уровню стека TCP / IP, поэтому, пока вы используете разные протоколы транспортного уровня стека, вы можете иметь несколько процессов, прослушивающих один и тот же : сочетание.

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

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

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

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

Давайте будем гением компьютера.