Могут ли два приложения прослушивать один и тот же порт?
Могут ли два приложения на одном компьютере связываться с одним и тем же портом и IP-адресом? Если сделать еще один шаг вперед, может ли одно приложение прослушивать запросы, приходящие с определенного IP, а другое - на другой удаленный IP? Я знаю, что у меня может быть одно приложение, которое запускает два потока (или вилки) для одинакового поведения, но могут ли два приложения, которые не имеют ничего общего, делать то же самое?
16 ответов
Для TCP нет. Вы можете иметь только одно приложение, прослушивающее один и тот же порт одновременно. Теперь, если у вас есть две сетевые карты, вы можете заставить одно приложение прослушивать первый IP-адрес, а второе - второй IP-адрес, используя один и тот же номер порта.
Для UDP (Multicasts) несколько приложений могут подписаться на один и тот же порт.
Да (для TCP) вы можете прослушивать две программы в одном сокете, если программы предназначены для этого. Когда сокет создан первой программой, убедитесь, что SO_REUSEADDR
перед вами установлена опция bind()
, Тем не менее, это может быть не то, что вы хотите. При этом входящее TCP-соединение будет направлено на одну из программ, а не на обе, поэтому оно не дублирует соединение, оно просто позволяет двум программам обслуживать входящий запрос. Например, веб-серверы будут иметь несколько процессов, все слушающие через порт 80, и O/S отправляет новое соединение процессу, готовому принять новые соединения.
SO_REUSEADDR
Позволяет другим сокетам bind()
к этому порту, если к нему уже не подключен активный прослушивающий сокет. Это позволяет обойти эти сообщения об ошибках "Адрес уже используется" при попытке перезагрузить сервер после сбоя.
Да.
Могут сосуществовать несколько прослушивающих сокетов TCP, все они связаны с одним и тем же портом, при условии, что все они связаны с разными локальными IP-адресами. Клиенты могут подключаться к тому, что им нужно. Это исключает
0.0.0.0
(INADDR_ANY
).Могут сосуществовать несколько принятых сокетов, все из которых принимаются из одного и того же прослушивающего сокета, и все показывают тот же номер локального порта, что и прослушивающий сокет.
Несколько UDP-сокетов, все связанные с одним и тем же портом, могут сосуществовать при условии, что либо то же условие, что и в (1), либо все они имеют
SO_REUSEADDR
опция установлена перед привязкой.TCP-порты и UDP-порты занимают разные пространства имен, поэтому использование порта для TCP не исключает его использования для UDP, и наоборот.
Ссылка: Стивенс и Райт, TCP / IP Illustrated, том II.
В принципе нет.
Это не написано в камне; но так пишутся все API: приложение открывает порт, получает его дескриптор, и ОС уведомляет его (через этот дескриптор), когда приходит клиентское соединение (или пакет в случае UDP).
Если ОС позволяет двум приложениям открывать один и тот же порт, как она узнает, какое из них уведомить?
Но... есть способы обойти это:
- Как отметил Джед, вы можете написать "основной" процесс, который будет единственным, который действительно прослушивает порт и уведомляет других, используя любую логику, которую он хочет разделить клиентские запросы.
- В Linux и BSD (по крайней мере) вы можете установить правила "переназначения", которые перенаправляют пакеты с "видимого" порта на другие (где приложения прослушивают), в соответствии с любыми критериями, связанными с сетью (может быть, сеть происхождения или некоторые другие). простые формы балансировки нагрузки).
Да, безусловно. Насколько я помню, начиная с версии ядра 3.9 (не уверен в версии) и далее поддержка SO_REUSEPORT
был представлен. SO_RESUEPORT
разрешает привязку к одному и тому же порту и адресу, если первый сервер устанавливает эту опцию перед привязкой своего сокета.
Он работает как для TCP, так и для UDP. Обратитесь к ссылке для более подробной информации: SO_REUSEPORT
Примечание: принятый ответ больше не соответствует действительности, по моему мнению.
Нет. Только одно приложение может связываться с портом за раз, и поведение, если связывание принудительно, является неопределенным.
С многоадресными сокетами - которые звучат так, как если бы они не были близки к тому, что вы хотите - более одного приложения могут связываться с портом, если SO_REUSEADDR установлен в опциях каждого сокета.
Вы можете сделать это, написав "основной" процесс, который принимает и обрабатывает все соединения, а затем передает их вашим двум приложениям, которым необходимо прослушивать один и тот же порт. Это подход, который используют веб-серверы и тому подобное, поскольку многие процессы должны прослушивать 80.
Помимо этого, мы углубимся в специфику - вы пометили и TCP, и UDP, что это? Кроме того, какая платформа?
Вы можете иметь одно приложение, прослушивающее один порт для одного сетевого интерфейса. Поэтому вы могли бы иметь:
httpd
прослушивание через удаленно доступный интерфейс, например192.168.1.1:80
- другой демон слушает
127.0.0.1:80
Пример использования может быть использовать httpd
в качестве балансировщика нагрузки или прокси.
Просто чтобы поделиться тем, что упомянул @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
Когда вы создаете 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-адресов.
Другой способ - использовать программу, прослушивающую один порт, который анализирует тип трафика (ssh, https и т. Д.), Который он перенаправляет внутренне на другой порт, который прослушивает "настоящая" служба.
Например, для Linux sslh: https://github.com/yrutschle/sslh
Да.
Из этой статьи:
https://lwn.net/Articles/542629/
Новая опция сокетов позволяет нескольким сокетам на одном хосте связываться с одним и тем же портом
Если хотя бы один из удаленных IP-адресов уже известен, статичен и выделен для общения только с одним из ваших приложений, вы можете использовать правило iptables (таблица nat, chain PREROUTING) для перенаправления входящего трафика с этого адреса на "общий" локальный порт для любой другой порт, где на самом деле слушает соответствующее приложение.
Я пробовал следующее, с 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
И да и нет. Только одно приложение может активно прослушивать порт. Но это приложение может завещать свое соединение с другим процессом. Таким образом, вы можете иметь несколько процессов, работающих на одном порту.
Два приложения могут прослушивать один и тот же порт на одном сетевом интерфейсе.
Для указанного сетевого интерфейса и порта может быть только один прослушивающий сокет, но этот сокет может использоваться несколькими приложениями.
Если у вас есть сокет прослушивания в процессе приложения, и вы fork
этот процесс, сокет будет унаследован, так что технически теперь будут два процесса, слушающие один и тот же порт.
Если под приложениями вы подразумеваете несколько процессов, то да, но, как правило, НЕТ. Например, сервер Apache запускает несколько процессов на одном и том же порту (обычно 80). Это делается путем назначения одного из процессов фактическому связыванию с портом, а затем использования этого процесса для передачи обслуживания различным процессам, которые принимают соединения.
Короткий ответ:
Судя по ответу, приведенному здесь. Вы можете иметь два приложения, прослушивающие один и тот же IP-адрес и номер порта, поэтому один из портов является портом UDP, а другой - портом TCP.
Объяснение:
Концепция порта применима к транспортному уровню стека TCP/IP, поэтому, если вы используете разные протоколы транспортного уровня стека, у вас может быть несколько процессов, прослушивающих один и тот же <ip-address>:<port>
сочетание.
Одно сомнение, что у людей есть, если два приложения работают на одном <ip-address>:<port>
комбинация, как клиент, работающий на удаленной машине, будет различать эти два? Если вы посмотрите на заголовок пакета IP-уровня ( https://en.wikipedia.org/wiki/IPv4), вы увидите, что биты с 72 по 79 используются для определения протокола, именно так можно провести различие.
Однако, если вы хотите иметь два приложения на одном TCP <ip-address>:<port>
комбинации, тогда ответ будет отрицательным (Интересным упражнением будет запуск двух виртуальных машин, предоставление им одинаковых IP-адресов, но разных MAC-адресов, и посмотреть, что произойдет - вы заметите, что иногда VM1 получает пакеты, а другие VM2 - пакеты - в зависимости от обновления кэша ARP).
Я чувствую, что заставляя два приложения работать на одном <op-address>:<port>
Вы хотите достичь какой-то балансировки нагрузки. Для этого вы можете запускать приложения на разных портах и писать правила IP-таблиц для разделения трафика между ними.
Также см. Ответ @user6169806.