Могут ли два приложения на одной машине связываться с одним и тем же портом и IP-адресом? Если пойти дальше, может ли одно приложение прослушивать запросы, поступающие с определенного IP-адреса, а другое - на другой удаленный IP-адрес? Я знаю, что у меня может быть одно приложение, которое запускает два потока (или вилки), чтобы иметь аналогичное поведение, но могут ли два приложения, у которых нет ничего общего, делать то же самое?
Могут ли два приложения прослушивать один и тот же порт?
Ответы (17)
Ответ различается в зависимости от рассматриваемой ОС. В общем, хотя:
Для TCP нет. У вас может быть только одно приложение, прослушивающее один и тот же порт одновременно. Теперь, если у вас есть 2 сетевые карты, вы можете настроить одно приложение для прослушивания первого IP-адреса, а второе - на втором IP-адресе, используя один и тот же номер порта.
Для UDP (Multicast) несколько приложений могут подписаться на один и тот же порт.
Изменить: начиная с ядра Linux 3.9 и новее, поддержка нескольких приложений, прослушивающих один и тот же порт, была добавлена с использованием параметра SO_REUSEPORT
. Более подробная информация доступна в этой статье lwn.net.
Да (для TCP) вы можете настроить прослушивание двух программ на одном сокете, если программы предназначены для этого. Когда сокет создается первой программой, убедитесь, что для сокета установлена опция SO_REUSEADDR
, прежде чем вы bind()
. Однако это может быть не то, что вам нужно. Это означает, что входящее TCP-соединение будет направлено одной из программ, а не обеим, поэтому оно не дублирует соединение, а просто позволяет двум программам обслуживать входящий запрос. Например, веб-серверы будут иметь несколько процессов, все прослушивающие порт 80, и операционная система отправляет новое соединение процессу, который готов принять новые соединения.
SO_REUSEADDR
Разрешает другим сокетам bind()
к этому порту, если к этому порту уже не привязан активный прослушивающий сокет. Это позволяет вам обойти сообщения об ошибках «Адрес уже используется» при попытке перезапустить сервер после сбоя.
SO_REUSEADDR
определенно не позволяет вам иметь два TCP-сокета в состоянии прослушивания одновременно, по крайней мере, в Unix. Он предназначен для обхода TIME_WAIT state
: unixguide.net/network/socketfaq/4.5.shtml < / а>. Это может работать в Windows, но вам не гарантируется, что запрос все равно достигнет нужного сервера).
- person Bruno; 07.05.2015
да.
Несколько прослушивающих сокетов TCP, привязанных к одному порту, могут сосуществовать при условии, что все они привязаны к разным локальным IP-адресам. Клиенты могут подключаться к тому, что им нужно. Это исключает
0.0.0.0
(INADDR_ANY
).Могут сосуществовать несколько принятых сокетов, все они принимаются от одного и того же прослушивающего сокета, и все они показывают тот же номер локального порта, что и прослушивающий сокет.
Несколько сокетов UDP, все привязанные к одному и тому же порту, могут сосуществовать при условии либо того же условия, что и в (1), либо для всех них была установлена опция
SO_REUSEADDR
перед привязкой.Порты TCP и порты UDP занимают разные пространства имен, поэтому использование порта для TCP не препятствует его использованию для UDP, и наоборот.
Ссылка: Стивенс и Райт, TCP / IP Illustrated, Том II.
В принципе нет.
Это не высечено на камне; но так написаны все API: приложение открывает порт, получает его дескриптор, а ОС уведомляет его (через этот дескриптор), когда приходит клиентское соединение (или пакет в случае UDP).
Если бы ОС позволяла двум приложениям открывать один и тот же порт, как бы она узнала, какое из них уведомлять?
Но ... есть способы обойти это:
- As Jed noted, you could write a 'master' process, which would be the only one that really listens on the port and notifies others, using any logic it wants to separate client requests.
- On Linux and BSD (at least) you can set up 'remapping' rules that redirect packets from the 'visible' port to different ones (where the apps are listening), according to any network related criteria (maybe network of origin, or some simple forms of load balancing).
iptables -m statistic --mode random --probability 0.5
это весело.
- person Jed Smith; 08.11.2009
listen()
включить. Скорее вопрос в том, чтобы открыть его в брандмауэре. Здесь слишком много ошибок, и все они не исправлены за 7 лет. Ответ также опускает случай привязки к другому локальному адресу с тем же номером порта. На самом деле это совершенно неверно.
- person user207421; 08.08.2019
Да, безусловно. Насколько я помню, начиная с версии ядра 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
в качестве балансировщика нагрузки или прокси.
Другой способ - использовать программу, прослушивающую один порт, которая анализирует тип трафика (ssh, https и т. Д.), Который он перенаправляет изнутри на другой порт, который прослушивает «настоящая» служба.
Например, для Linux sslh: https://github.com/yrutschle/sslh.
Когда вы создаете 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-адресов.
Если хотя бы один из удаленных IP-адресов уже известен, статичен и предназначен для общения только с одним из ваших приложений, вы можете использовать правило iptables (table nat, chain PREROUTING) для перенаправления входящего трафика с этого адреса на «общий» локальный порт на любой другой порт, на котором соответствующее приложение фактически прослушивает.
Да и нет. Только одно приложение может активно прослушивать порт. Но это приложение может завещать свою связь с другим процессом. Таким образом, у вас может быть несколько процессов, работающих с одним и тем же портом.
да.
Из этой статьи:
https://lwn.net/Articles/542629/
Новая опция сокета позволяет нескольким сокетам на одном хосте связываться с одним и тем же портом.
Просто чтобы поделиться тем, что упомянул @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
Если под приложениями вы имеете в виду несколько процессов, тогда да, но обычно НЕТ. Например, сервер 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-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.