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

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


person nadiv    schedule 07.11.2009    source источник
comment
Хороший подробный ответ о повторном использовании адресов / портов с несколькими сокетами: stackoverflow.com/questions/14388706/   -  person Bjarke Freund-Hansen    schedule 14.10.2014


Ответы (17)


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

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

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

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

person Chris Dail    schedule 07.11.2009
comment
одно приложение прослушивает один порт, поэтому порты существуют - чтобы позволить нескольким приложениям совместно использовать сеть без конфликтов. - person S.Lott; 07.11.2009
comment
Один слушатель на порт на каждый IP-адрес. Добавление еще одного сетевого интерфейса - это способ получить второй IP-адрес. Ваша платформа, вероятно, поддерживает виртуальные интерфейсы, что является еще одним способом получить два IP-адреса с помощью одной физической сетевой карты. - person John M; 10.11.2009
comment
Хотя до сих пор я придерживался того же мнения, оказалось, что я смог привязать два разных процесса к одному и тому же IP-адресу и TCP-порту! Это возможно, если вы установите ServerSocket.setReuseAddress (true) в Java перед привязкой к нему. Действительно неожиданное поведение. - person Eugen; 17.05.2013
comment
@Eugen также отмечает ошибку Java 7179799, которая может произойти в Windows с несколько версий Java. - person John McCarthy; 04.06.2013
comment
@Eugen, Chris Dail, Если приложение TCP использует порт, нет гарантии, что другое приложение не может также прослушивать / взаимодействовать с тем же портом? Другими словами, если apache (httpd) прослушивает порт 80, это не гарантирует, что какое-то другое вредоносное приложение не будет прослушивать / взаимодействовать через порт 80? А что с UDP? Может ли вредоносное приложение перехватить UDP-соединение другого приложения, использующего тот же порт? - person trusktr; 17.08.2013
comment
Вопрос касается Linux, но ответ здесь довольно подробный и охватывает другие: stackoverflow.com/a/14388707/230537 - person abeyer; 28.08.2013
comment
(1) Фактическое значение вашего ответа: «Для TCP, да, при условии ...» (2) Многоадресная рассылка не является предварительным условием для совместного использования порта UDP, но SO_REUSEADDR. - person user207421; 23.09.2013
comment
Для UDP (многоадресная передача) несколько приложений могут подписаться на один и тот же порт. Если от клиента пришел один пакет, какое приложение его получит? - person Yang Juven; 18.08.2014
comment
Всем привет, что можно почитать, чтобы глубже разобраться в этой теме? В частности, я хочу понять «почему» того, что сказал @JohnM: один слушатель на порт на каждый IP-адрес. - person Maria Ines Parnisari; 23.12.2014
comment
@Chris, этот ответ вводит в заблуждение и должен быть отредактирован / удален. - person Pacerier; 18.09.2015
comment
@Chris и что произойдет, если два приложения прослушивают один и тот же порт, у меня есть мемдамп, где 9 локальных адресов прослушивают один и тот же порт - person Aequitas; 04.12.2015
comment
Для 2-х сетевых карт не обязательно иметь 2 IP-адреса. Просто попросите ядро ​​прослушивать второй IP-адрес на этом интерфейсе. У вас может быть столько IP-адресов, сколько вы хотите на интерфейсе. - person alexchandel; 08.09.2016
comment
Был ли у вас источник об этом? Мне нужна моя статья. Спасибо - person Renan Cavalieri; 06.10.2016
comment
В Windows есть функции совместного использования портов. В Linux вы можете (небезопасно) совместно использовать fd (дескриптор / дескриптор сокета), но на самом деле он не будет работать, как общий порт в Windows. Этот ответ не совсем верен, за исключением строгих требований BSD Sockets, которые не определяют такое совместное использование. В случае, когда несколько процессов прослушивают один и тот же порт, при настройке для этого самым последним прослушивателем является тот, который получает соединения / клиентов / сокеты. - person Shaun Wilson; 31.03.2017
comment
Это не совсем так, см. Ответ JNewton. - person soger; 04.12.2018
comment
@YangJuven, каков ответ на твой вопрос? - person jpell; 16.12.2019
comment
@YangJuven Все сокеты получат многоадресный пакет. Для одноадресного UDP поведение зависит от ОС. - person dbush; 15.05.2021

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

SO_REUSEADDR

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

person JNewton    schedule 11.01.2012
comment
TCP + UDP теперь работает (с учетом достаточно нового ядра). См. Ссылку, которую я добавил к ответу. - person dpb; 30.04.2013
comment
Этот ответ неверен, если все сокеты не привязаны к отдельным IP-адресам, ни один из которых не является INADDR_ANY, или если вы не находитесь в Windows, где результат не определен. - person user207421; 23.07.2013
comment
Можете ли вы подробнее рассказать о том, как данные поступают в определенное приложение через один и тот же порт? Есть ли какие-либо проблемы безопасности, о которых следует думать, когда приложения используют SO_REUSEADDR или SO_REUSEPORT? - person trusktr; 19.08.2013
comment
@EJP Можете ли вы также взглянуть на мой предыдущий комментарий? - person trusktr; 19.08.2013
comment
Если клиент подключается к порту IP1 :, он разговаривает с сокетом, который прослушивает порт IO1 :. Аналогично для IP2: порт и т. Д. - person user207421; 23.09.2013
comment
ПРИМЕЧАНИЕ вы сказали, что изначально ДВЕ программы могут СЛУШАТЬ, но не могут запускать процесс / отдельный обряд адресации памяти? вопрос заключается в запуске или наличии двух процессов в одном и том же порте, что вообще невозможно ... ТАКОЕ служба может быть запущена на порту, и один или несколько клиентов могут прослушивать службу на этом порту ... - person Gokul E; 25.10.2013
comment
@Gokul Серверы слушают. Клиенты подключаются. Не запутайте проблему, злоупотребляя стандартной терминологией. - person user207421; 12.11.2013
comment
@EJP да ... и, надеюсь, я хочу получить ответ о разнице между прослушиванием и подключением ... Может быть, я немного запутался ... извините ... Я подумал, что когда две программы прослушивают порт, связь будет запутана для клиент какой программе обслуживает в порту !!! .. так ли это? извините, если я неправильно спросил .. - person Gokul E; 15.11.2013
comment
SO_REUSEADDR определенно не позволяет вам иметь два TCP-сокета в состоянии прослушивания одновременно, по крайней мере, в Unix. Он предназначен для обхода TIME_WAIT state: unixguide.net/network/socketfaq/4.5.shtml < / а>. Это может работать в Windows, но вам не гарантируется, что запрос все равно достигнет нужного сервера). - person Bruno; 07.05.2015
comment
@GokulEzhumalai Разница в том, что серверы слушают, а клиенты подключаются. Я уже сказал это. - person user207421; 02.02.2016
comment
Да, спасибо, я понятия не имел, что происходит, пока не понял, что два экземпляра apache работают: один со старой и один с новой конфигурацией, и я получал случайные ответы. - person soger; 04.12.2018

да.

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

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

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

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

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

person user207421    schedule 23.09.2013
comment
есть ли у вас под рукой ссылка? Возможность сосуществования TCP-UDP - это как раз мой вопрос. Заранее спасибо:) - person Wolf; 29.01.2014
comment
@Wolf Просто попробуй. Это все доказательства, которые вам действительно нужны. Я цитирую Stevens & Wright: лучше этого не найти. - person user207421; 29.01.2014
comment
Спасибо за ответ, читать нужно еще внимательнее. Вы уже писали, что UDP и TCP могут сосуществовать. - person Wolf; 29.01.2014

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

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

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

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

  1. 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).
person Javier    schedule 07.11.2009
comment
iptables -m statistic --mode random --probability 0.5 это весело. - person Jed Smith; 08.11.2009
comment
Что именно означает "Открывает порт"? Я понимаю предложение, но знаете ли вы, что именно делает система, когда открывает порт и обрабатывает его? Я знаю, что когда вы хотите открыть порт с помощью TCP, вы получаете поток, и этот поток является вашим соединением с пультом дистанционного управления, но я ищу в Интернете и не нашел очень хорошего объяснения. - person Samuel; 16.12.2010
comment
@Samuel: открытие порта (в режиме сервера) означает получение дескриптора файла, и когда система получает пакет SYN на этот номер порта, отвечает SYN + ACK и генерирует событие в соответствующем дескрипторе файла. приложение отвечает на это событие вызовом accept (), который создает новый дескриптор файла, связанный с конкретным потоком, оставляя исходный дескриптор сервера свободным для получения новых подключений от клиентов - person Javier; 16.12.2010
comment
Этот ответ нельзя считать правильным. Он полностью игнорирует существование SO_REUSEADDR и SO_REUSEPORT. - person user207421; 16.09.2012
comment
@ Хавьер Нет, это не так. Открытие порта с точки зрения серверного приложения происходит, когда вы привязываете прослушивающий сокет, или, скорее, привязываете сокет, который вы собираетесь listen() включить. Скорее вопрос в том, чтобы открыть его в брандмауэре. Здесь слишком много ошибок, и все они не исправлены за 7 лет. Ответ также опускает случай привязки к другому локальному адресу с тем же номером порта. На самом деле это совершенно неверно. - person user207421; 08.08.2019

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

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

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

person piyush    schedule 13.06.2017
comment
Полностью верно. Если бы это было неправдой, как мог бы работать Wireshark? - person Staszek; 09.11.2017
comment
@Staszek Wireshark не слушает порты. Он работает на уровне пакетов. - person user207421; 15.05.2018
comment
О, это имело бы смысл. В любом случае прослушивание двух портов двумя приложениями, безусловно, возможно. - person Staszek; 15.05.2018
comment
Спасибо, никогда бы не узнал, почему используемая мной библиотека http-сервера позволяет связывать одни и те же порты, если это не этот ответ. - person tga; 20.11.2020

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

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

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

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

person Jed Smith    schedule 07.11.2009
comment
оба интересны мне. Платформа - это окна, но если для Linux ответ будет другим, было бы неплохо узнать - person nadiv; 07.11.2009
comment
Не существует такого понятия, как многоадресный сокет. Есть сокеты UDP. Многоадресная рассылка не является предварительным условием для SO_REUSEADDR. - person user207421; 23.09.2013

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

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

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

person Tomas Tomecek    schedule 20.03.2015

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

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

person Mitchbcn    schedule 27.08.2014
comment
На windows есть такая прога? Мне нужно, чтобы и мой локальный сервер IIS, и брокер ActiveMQ прослушивали порт 443. - person Harvey Lin; 25.10.2019

Когда вы создаете 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-адресов.

person cjs    schedule 18.04.2016

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

person Stemar    schedule 05.10.2011

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

person rajesh    schedule 15.04.2013
comment
@trusktr, я думаю, он имел в виду это - person warvariuc; 12.08.2014

да.

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

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

person user6169806    schedule 07.04.2016
comment
Хорошая ссылка, однако не пишите там эту строку - опция SO_REUSEPORT нестандартна - person Sahil Singh; 16.02.2017

Просто чтобы поделиться тем, что упомянул @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   
person Amit Parashar    schedule 21.07.2019

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

person nitinsh99    schedule 23.09.2013

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

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

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

person warvariuc    schedule 30.07.2014

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

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

Следуя ответу, данному здесь. У вас может быть два приложения, прослушивающих один и тот же 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.

person Sahil Singh    schedule 11.09.2015