Czy dwie aplikacje mogą nasłuchiwać na tym samym porcie?


283

Czy dwie aplikacje na tym samym komputerze mogą łączyć się z tym samym portem i adresem IP? Idąc krok dalej, czy jedna aplikacja może nasłuchiwać żądań pochodzących z określonego adresu IP, a druga do innego zdalnego adresu IP? Wiem, że mogę mieć jedną aplikację, która uruchamia dwa wątki (lub widelce), aby mieć podobne zachowanie, ale czy dwie aplikacje, które nie mają ze sobą nic wspólnego, mogą zrobić to samo?


2
Aby uzyskać szczegółową odpowiedź na temat ponownego wykorzystywania adresów / portów z wieloma gniazdami: stackoverflow.com/questions/14388706/…
Bjarke Freund-Hansen

Odpowiedzi:


248

Odpowiedź różni się w zależności od rozważanego systemu operacyjnego. Ogólnie jednak:

W przypadku TCP nie. Możesz mieć jednocześnie tylko jedną aplikację nasłuchującą na tym samym porcie. Teraz, jeśli masz 2 karty sieciowe, możesz mieć jedną aplikację nasłuchującą na pierwszym adresie IP, a drugą na drugim adresie IP, używając tego samego numeru portu.

W przypadku UDP (multiemisje) wiele aplikacji może subskrybować ten sam port.

Edycja: Od wersji jądra Linux 3.9 i nowszych dodano obsługę wielu aplikacji nasłuchujących na tym samym porcie za pomocą tej SO_REUSEPORTopcji. Więcej informacji jest dostępnych w tym artykule lwn.net.


22
„jedna aplikacja nasłuchuje na jednym porcie”, dlatego istnieją porty - aby umożliwić wielu aplikacjom współdzielenie sieci bez konfliktów.
S.Lott,

46
Jeden detektor na port na adres IP. Dodanie innego interfejsu sieciowego to sposób na uzyskanie drugiego adresu IP. Twoja platforma prawdopodobnie obsługuje interfejsy wirtualne, co jest innym sposobem na uzyskanie dwóch adresów IP za pomocą jednej fizycznej karty sieciowej.
John M,

7
Chociaż do tej pory byłem tego samego zdania, okazało się, że mogłem powiązać dwa różne procesy z tym samym portem IP i TCP! Jest to możliwe, jeśli ustawisz ServerSocket.setReuseAddress (true) w Javie przed powiązaniem. Naprawdę nieoczekiwane zachowanie.
Eugen,

7
(1) Rzeczywiste znaczenie twojej odpowiedzi brzmi „Dla TCP, tak, pod warunkiem ...” (2) Multicast nie jest warunkiem wstępnym udostępniania portów UDP, ale SO_REUSEADDR jest.
Markiz Lorne

12
W przypadku UDP (multiemisje) wiele aplikacji może subskrybować ten sam port. Jeśli jeden pakiet przyszedł od klienta, która aplikacja go odbiera?
Yang Juven

123

Tak (dla TCP) możesz mieć dwa programy nasłuchujące na tym samym gnieździe, jeśli programy są do tego przeznaczone. Gdy gniazdo jest tworzone przez pierwszy program, upewnij się, że SO_REUSEADDRopcja jest ustawiona na gnieździe przed tobą bind(). Jednak może to nie być to, czego chcesz. To, co robi, to przychodzące połączenie TCP zostanie przekierowane do jednego z programów, a nie do obu, więc nie powiela połączenia, pozwala tylko dwóm programom na obsługę przychodzącego żądania. Na przykład, serwery WWW będą miały wiele procesów nasłuchujących na porcie 80, a O / S wyśle ​​nowe połączenie do procesu, który jest gotowy na przyjęcie nowych połączeń.

SO_REUSEADDR

Zezwala innym gniazdom na bind()ten port, chyba że aktywne gniazdo nasłuchujące jest już powiązane z tym portem. Umożliwia to obejście komunikatów o błędach „Adres już używany” podczas próby ponownego uruchomienia serwera po awarii.


1
TCP + UDP teraz działa (biorąc pod uwagę wystarczająco nowe jądro). Zobacz link dodany do odpowiedzi.
dpb

3
Ta odpowiedź jest nieprawidłowa, chyba że wszystkie gniazda są przypisane do różnych adresów IP, z których żaden nie jest INADDR_ANY, lub chyba, że ​​korzystasz z systemu Windows, którego wynik jest niezdefiniowany.
Markiz Lorne

1
Czy możesz rozwinąć sposób przesyłania danych do konkretnej aplikacji na tym samym porcie? Czy istnieją jakieś obawy związane z bezpieczeństwem, o których należy pamiętać, gdy aplikacje używają SO_REUSEADDR lub SO_REUSEPORT?
trusktr,

@EJP Czy możesz również spojrzeć na mój poprzedni komentarz?
trusktr,

3
SO_REUSEADDRz pewnością nie pozwala na jednoczesne słuchanie dwóch gniazd TCP, przynajmniej na Uniksie. Ma na celu ominięcieTIME_WAIT state : unixguide.net/network/socketfaq/4.5.shtml . Może to działać w systemie Windows, ale nie ma gwarancji, że żądanie i tak dotrze do właściwego serwera).
Bruno,

48

Tak.

  1. Wiele nasłuchujących gniazd TCP, wszystkie powiązane z tym samym portem, może współistnieć, pod warunkiem że wszystkie są powiązane z różnymi lokalnymi adresami IP. Klienci mogą łączyć się z dowolnymi, których potrzebują. To wyklucza 0.0.0.0( INADDR_ANY).

  2. Może istnieć wiele akceptowanych gniazd, wszystkie przyjmowane z tego samego gniazda nasłuchującego, wszystkie z tym samym numerem portu lokalnego co gniazdo nasłuchujące.

  3. Wiele gniazd UDP wszystkie powiązane z tym samym portem mogą wszystkie istnieć jednocześnie, pod warunkiem, że są takie same warunki jak w (1) lub wszystkie mają SO_REUSEADDRustawioną opcję przed powiązaniem.

  4. Porty TCP i porty UDP zajmują różne przestrzenie nazw, więc użycie portu dla TCP nie wyklucza jego użycia dla UDP i odwrotnie.

Odniesienie: Stevens & Wright, Illustrated TCP / IP, Tom II.


masz pod ręką link? Moim pytaniem jest możliwość współistnienia protokołu TCP-UDP. Z góry dziękuję :)
Wolf,

1
@Wolf Po prostu spróbuj. To wszystko, czego naprawdę potrzebujesz. Moje cytowanie to Stevens & Wright: nie da się nic lepszego.
Markiz Lorne

1
Dzięki za odpowiedź, muszę przeczytać jeszcze bardziej uważnie. Już napisałeś, że UDP i TCP mogą współistnieć .
Wolf

47

W zasadzie nie.

Nie jest napisane w kamieniu; ale w taki sposób zapisywane są wszystkie interfejsy API: aplikacja otwiera port, pobiera do niego uchwyt, a system operacyjny powiadamia go (za pośrednictwem tego uchwytu), gdy nadchodzi połączenie klienta (lub pakiet w przypadku UDP).

Jeśli system operacyjny zezwoli na otwarcie dwóch aplikacji przez ten sam port, skąd będzie wiedział, o której powiadomić?

Ale ... są na to sposoby:

  1. Jak zauważył Jed , możesz napisać proces „master”, który byłby jedynym, który naprawdę nasłuchuje na porcie i powiadamia innych, używając dowolnej logiki, jaką chce oddzielić żądania klienta.
    • W Linuksie i BSD (przynajmniej) możesz skonfigurować reguły „odwzorowywania”, które przekierowują pakiety z „widocznego” portu do różnych (tam, gdzie aplikacje nasłuchują), zgodnie z dowolnymi kryteriami związanymi z siecią (np. Siecią pochodzenia lub proste formy równoważenia obciążenia).

37
iptables -m statistic --mode random --probability 0.5jest zabawne.
Jed Smith

1
Co dokładnie oznacza „Otwiera port”? Rozumiem zdanie, ale czy wiesz, co dokładnie robi system, gdy otwiera port i obsługuje go? Wiem, że kiedy chcesz otworzyć port za pomocą TCP, dostajesz strumień i ten strumień to twoje połączenie ze zdalnym, ale szukam w Internecie i nie znalazłem dobrego wyjaśnienia.
Samuel,

4
@Samuel: otwarcie portu (w trybie serwera) oznacza uzyskanie deskryptora pliku, a gdy system otrzyma pakiet SYN na ten numer portu, odpowiada SYN + ACK i generuje zdarzenie na powiązanym deskryptorze pliku. aplikacja reaguje na to zdarzenie za pomocą wywołania accept (), które tworzy nowy deskryptor pliku skojarzony z określonym strumieniem, pozostawiając oryginalnemu deskryptorowi serwera swobodę uzyskiwania nowych połączeń od klientów
Javier,

7
Tej odpowiedzi nie można uznać za poprawną. Całkowicie pomija istnienie zarówno SO_REUSEADDR, jak i SO_REUSEPORT.
Markiz Lorne

@Javier Nie, nie ma. Otwarcie portu z punktu widzenia aplikacji serwera ma miejsce podczas łączenia gniazda nasłuchującego, a raczej gniazda, które masz zamiar podłączyć listen(). Bardziej prawdopodobne jest pytanie o otwarcie go w zaporze ogniowej. Zbyt wiele błędów tutaj i wszystkie nieskorygowane w ciągu 7 lat. Odpowiedź również pomija przypadek powiązania z innym adresem lokalnym o tym samym numerze portu. W rzeczywistości jest to całkowicie niepoprawne.
Markiz Lorne

27

Tak, zdecydowanie . O ile pamiętam Od jądra w wersji 3.9 (nie jestem pewien co do wersji) wprowadzono obsługę tego SO_REUSEPORT. SO_RESUEPORTpozwala na powiązanie z dokładnie tym samym portem i adresem, o ile pierwszy serwer ustawia tę opcję przed powiązaniem swojego gniazda.

Działa zarówno dla TCP, jak i UDP . Więcej informacji znajduje się w łączu: SO_REUSEPORT

Uwaga : Akceptowana odpowiedź nie jest już zgodna z moją opinią.


2
Całkowita prawda. Jeśli to nie prawda, jak mógłby działać Wireshark?
Staszek

5
@Staszek Wireshark nie słucha portów. Działa na poziomie pakietu.
Markiz Lorne

To miałoby sens. W każdym razie, nasłuchiwanie dwóch portów przez 2 aplikacje jest z pewnością możliwe.
Staszek

18

Nie. Tylko jedna aplikacja może jednocześnie łączyć się z portem, a zachowanie, jeśli wymuszenie jest nieokreślone.

Dzięki gniazdom multiemisji - które brzmią jak nigdzie w pobliżu tego, co chcesz - więcej niż jedna aplikacja może połączyć się z portem, o ile SO_REUSEADDR jest ustawione w opcjach każdego gniazda.

Możesz to zrobić, pisząc proces „master”, który akceptuje i przetwarza wszystkie połączenia, a następnie przekazuje je dwóm aplikacjom, które muszą nasłuchiwać na tym samym porcie. Takie podejście przyjmują serwery WWW i takie, ponieważ wiele procesów musi słuchać 80.

Poza tym zajmujemy się szczegółami - otagowałeś zarówno TCP, jak i UDP, co to jest? Jaka platforma?


oba są dla mnie interesujące. Platformą jest Windows, ale jeśli odpowiedź jest inna dla Linuksa, dobrze byłoby wiedzieć
nadiv

8
Nie ma czegoś takiego jak gniazdo multiemisji. Istnieją gniazda UDP. Multicast nie jest warunkiem wstępnym dla SO_REUSEADDR.
Markiz Lorne

3

Możesz mieć jedną aplikację nasłuchującą na jednym porcie dla jednego interfejsu sieciowego. Dlatego możesz mieć:

  1. httpd nasłuch na zdalnie dostępnym interfejsie, np 192.168.1.1:80
  2. inny demon nasłuchuje 127.0.0.1:80

Przykładem użycia może być użycie httpdmodułu równoważenia obciążenia lub serwera proxy.


3

Innym sposobem jest użycie programu nasłuchującego w jednym porcie, który analizuje rodzaj ruchu (ssh, https itp.), Który przekierowuje wewnętrznie do innego portu, na którym nasłuchuje „prawdziwa” usługa.

Na przykład dla systemu Linux sslh: https://github.com/yrutschle/sslh


Czy jest taki program w systemie Windows? Potrzebuję, aby mój lokalny serwer IIS i broker ActiveMQ nasłuchiwały na porcie 443
Harvey Lin

3

Podczas tworzenia połączenia TCP należy poprosić o połączenie z określonym adresem TCP, który jest kombinacją adresu IP (v4 lub v6, w zależności od używanego protokołu) i portu.

Gdy serwer nasłuchuje połączeń, może poinformować jądro, że chce nasłuchiwać określonego adresu IP i portu, tj. Jednego adresu TCP lub tego samego portu na każdym z adresów IP hosta (zwykle określanego za pomocą adresu IP 0.0.0.0), która jest skutecznie słuchać na wiele różnych „adresów TCP” (na przykład 192.168.1.10:8000, 127.0.0.1:8000itd)

Nie, nie możesz mieć dwóch aplikacji nasłuchujących na tym samym „adresie TCP”, ponieważ kiedy nadejdzie wiadomość, skąd jądro będzie wiedziało, która aplikacja ma przekazać wiadomość?

Jednak w większości systemów operacyjnych możesz skonfigurować kilka adresów IP na jednym interfejsie (np. Jeśli masz 192.168.1.10na interfejsie, możesz również skonfigurować 192.168.1.11, jeśli nikt inny w sieci go nie używa), aw takich przypadkach możesz mogą mieć osobne aplikacje nasłuchujące na porcie 8000na każdym z tych dwóch adresów IP.


2

Jeśli co najmniej jeden ze zdalnych adresów IP jest już znany, statyczny i przeznaczony do rozmowy tylko z jedną z twoich aplikacji, możesz użyć reguły iptables (tabela nat, łańcuch PREROUTING), aby przekierować przychodzący ruch z tego adresu na „wspólny” port lokalny do każdy inny port, na którym właściwa aplikacja faktycznie nasłuchuje.


1

Tak i nie. Tylko jedna aplikacja może aktywnie nasłuchiwać na porcie. Ale ta aplikacja może przekazać swoje połączenie z innym procesem. Możesz mieć wiele procesów działających na tym samym porcie.


@trusktr, myślę, że miał na myśli to
warvariuc


0

Jeśli przez aplikacje rozumiesz wiele procesów, to tak, ale ogólnie NIE. Na przykład serwer Apache uruchamia wiele procesów na tym samym porcie (zazwyczaj 80). Robi się to poprzez wyznaczenie jednego z procesów do faktycznego połączenia z portem, a następnie użycie tego procesu do przekazania różnych procesów, które przyjmują połączenia.


0

Możesz zmusić dwie aplikacje do nasłuchiwania tego samego portu w tym samym interfejsie sieciowym.

Może być tylko jedno gniazdo nasłuchujące dla określonego interfejsu sieciowego i portu, ale to gniazdo może być współużytkowane przez kilka aplikacji.

Jeśli masz proces nasłuchiwania w procesie aplikacji, a ty forkten proces, gniazdo zostanie odziedziczone, więc technicznie będą teraz dwa procesy nasłuchujące na tym samym porcie.


0

Próbowałem następujące, z socat:

socat TCP-L:8080,fork,reuseaddr -

I chociaż nie nawiązałem połączenia z gniazdem, nie mogę słuchać dwa razy na tym samym porcie, pomimo tej reuseaddropcji.

Dostaję tę wiadomość (której się wcześniej spodziewałem):

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

0

Wystarczy podzielić się tym, o czym wspomniał @jnewton. Uruchomiłem proces nginx i osadzony proces tomcat na moim komputerze Mac. Widzę oba przebieg procesu przy 8080.

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

-2

Krótka odpowiedź:

Przechodząc od odpowiedzi podanej tutaj . Możesz mieć dwie aplikacje nasłuchujące na tym samym adresie IP i numerze portu, więc jeden z nich jest portem UDP, a drugi portem TCP.

Wyjaśnienie:

Koncepcja portu jest istotna na warstwie transportowej stosu TCP / IP, więc dopóki używasz różnych protokołów warstwy transportowej stosu, możesz mieć wiele procesów nasłuchujących na tej samej <ip-address>:<port>kombinacji.

Jedną z wątpliwości, które ludzie mają, jest to, że jeśli dwie aplikacje działają na tej samej <ip-address>:<port>kombinacji, w jaki sposób klient działający na zdalnym komputerze rozróżnia te dwie? Jeśli spojrzysz na nagłówek pakietu warstwy IP ( https://en.wikipedia.org/wiki/IPv4#Header ), zobaczysz, że do zdefiniowania protokołu używane są bity od 72 do 79, w ten sposób można dokonać rozróżnienia.

Jeśli jednak chcesz mieć dwie aplikacje w tej samej <ip-address>:<port>kombinacji TCP , to odpowiedź brzmi nie (ciekawe ćwiczenie to uruchomienie dwóch maszyn wirtualnych, nadanie im tego samego adresu IP, ale różnych adresów MAC i zobacz, co się stanie - zauważysz to czasami VM1 otrzyma pakiety, a innym razem VM2 otrzyma pakiety - w zależności od odświeżenia pamięci podręcznej ARP).

Wydaje mi się, że poprzez uruchomienie dwóch aplikacji na tym samym <op-address>:<port>, chcesz osiągnąć pewnego rodzaju równoważenie obciążenia. W tym celu możesz uruchamiać aplikacje na różnych portach i pisać reguły tabeli IP, aby rozdzielić ruch między nimi.

Zobacz także odpowiedź @ user6169806.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.