İki uygulama aynı bağlantı noktasını dinleyebilir mi?


283

Aynı makinedeki iki uygulama aynı bağlantı noktasına ve IP adresine bağlanabilir mi? Bir adım daha ileri giderek, bir uygulama belirli bir IP'den diğerini başka bir uzak IP'ye gelen istekleri dinleyebilir mi? Benzer davranış için iki iş parçacığı (veya çatal) başlatan bir uygulama olabilir biliyorum, ama ortak bir şey olmayan iki uygulama aynı şeyi yapabilir miyim?


2
Birden fazla soketli adresleri / bağlantı noktalarını yeniden kullanma konusunda ayrıntılı ve ayrıntılı bir yanıt için: stackoverflow.com/questions/14388706/…
Bjarke Freund-Hansen

Yanıtlar:


248

Cevap, hangi işletim sisteminin dikkate alındığına bağlı olarak değişir. Genel olarak:

TCP için, no. Aynı anda aynı bağlantı noktasını dinleyen bir uygulamanız olabilir. Şimdi 2 ağ kartınız varsa, aynı bağlantı noktası numarasını kullanarak bir uygulamanın ilk IP'yi ve ikinci IP'yi ikinci IP'de dinlemesini sağlayabilirsiniz.

UDP (Çok Noktaya Yayın) için, birden çok uygulama aynı bağlantı noktasına abone olabilir.

Düzenleme: Linux Kernel 3.9 ve sonrası, aynı bağlantı noktasını dinleyen birden çok uygulama desteği SO_REUSEPORTseçeneği kullanılarak eklenmiştir . Daha fazla bilgiyi bu lwn.net makalesinde bulabilirsiniz.


22
"tek bir bağlantı noktasında dinleme yapan tek bir uygulama" bağlantı noktalarının var olmasının nedeni budur - birden çok uygulamanın ağı çakışma olmadan paylaşmasına izin vermek için.
S.Lott

46
IP adresi başına port başına bir dinleyici. Başka bir ağ arabirimi eklemek, ikinci bir IP adresi almanın bir yoludur. Platformunuz muhtemelen bir fiziksel ağ kartıyla iki IP adresi almanın başka bir yolu olan sanal arayüzleri destekliyor.
John M

7
Şimdiye kadar aynı görüşte olmama rağmen, aynı ip ve TCP portuna iki farklı işlemi bağlayabildim! Java'da ServerSocket.setReuseAddress (true) değerini bağlamadan önce ayarlarsanız bu mümkündür. Gerçekten beklenmedik davranış.
Eugen

7
(1) Yanıtınızın asıl anlamı 'TCP için evet, sağlanmıştır ...' (2) Çok noktaya yayın, UDP bağlantı noktası paylaşımı için bir önkoşul değildir, ancak SO_REUSEADDR'dir.
Lorne Marquis

12
UDP (Çok Noktaya Yayın) için, birden çok uygulama aynı bağlantı noktasına abone olabilir. Bir paket istemciden gelmişse, hangi uygulama onu alır?
Yang Juven

123

Evet (TCP için), programlar bu şekilde tasarlanmışsa, aynı sokette iki programın dinlemesini sağlayabilirsiniz. Soket ilk program tarafından oluşturulduğunda, SO_REUSEADDRseçeneğin sizden önce soket üzerinde ayarlandığından emin olun bind(). Ancak, bu istediğiniz şey olmayabilir. Bunun yaptığı, gelen bir TCP bağlantısının her ikisine değil programlardan birine yönlendirilmesidir , bu nedenle bağlantıyı çoğaltmaz, sadece iki programın gelen isteğe hizmet vermesine izin verir. Örneğin, web sunucularının 80 numaralı bağlantı noktasını dinleyen birden çok işlemi olur ve O / S, yeni bağlantıları kabul etmeye hazır olan işleme yeni bir bağlantı gönderir.

SO_REUSEADDR

bind()Bağlantı noktasına zaten bağlı etkin bir dinleme soketi yoksa, diğer bağlantı noktalarının bu bağlantı noktasına gitmesine izin verir . Bu, bir çökme sonrasında sunucunuzu yeniden başlatmaya çalıştığınızda "Adres zaten kullanımda" hata iletilerini aşmanıza olanak tanır.


1
TCP + UDP şimdi çalışıyor (yeterince yeni bir çekirdek verildiğinde). Cevaba eklediğim bağlantıya bakın.
dpb

3
Tüm yuvalar hiçbiri INADDR_ANY olan farklı IP adreslerine bağlı değilse veya sonucun tanımsız olduğu Windows'ta değilseniz bu yanıt doğru değildir.
Lorne Marquis

1
Verilerin aynı bağlantı noktasındaki belirli bir uygulamaya nasıl gittiğini genişletebilir misiniz? Uygulamaların SO_REUSEADDR veya SO_REUSEPORT kullandığında düşünülmesi gereken güvenlik endişeleri var mı?
trusktr

@EJP Önceki yorumuma da göz atabilir misiniz?
trusktr

3
SO_REUSEADDRen azından Unix'te aynı anda dinleme durumunda iki TCP soketi olmasına izin vermez. Almak çevrede için yaratılmış TIME_WAIT state: unixguide.net/network/socketfaq/4.5.shtml . Windows üzerinde çalışabilir, ancak isteğin yine de doğru sunucuya ulaşacağı garanti edilmez).
Bruno

48

Evet.

  1. Hepsi aynı bağlantı noktasına bağlı olan birden fazla dinleme TCP soketi, hepsi farklı yerel IP adreslerine bağlı olduğu sürece birlikte bulunabilir. İstemciler hangisine ihtiyaç duyarlarsa bağlansınlar. Bu 0.0.0.0( INADDR_ANY) içermez .

  2. Hepsi aynı dinleme soketinden kabul edilen ve tümü dinleme soketi ile aynı yerel bağlantı noktası numarasını gösteren birden fazla kabul edilen soket birlikte bulunabilir.

  3. Aynı bağlantı noktasına bağlı olan birden fazla UDP soketi, (1) 'deki koşulla birlikte sağlanabilir veya hepsinin SO_REUSEADDRbağlamadan önce seçeneği ayarlanmış olabilir.

  4. TCP bağlantı noktaları ve UDP bağlantı noktaları farklı ad alanlarına sahiptir, bu nedenle TCP için bir bağlantı noktasının kullanılması UDP için kullanılmasını engellemez ve bunun tersi de geçerlidir.

Kaynak: Stevens & Wright, TCP / IP Resimli, Cilt II.


elinizde bir bağlantı var mı? TCP-UDP bir arada yaşama fırsatı benim asıl soru. Şimdiden teşekkürler :)
Wolf

1
@Wolf Sadece dene. Gerçekten ihtiyacın olan tek şey bu. Atıfım Stevens & Wright: Bundan daha iyisi olamaz.
Lorne Marquis

1
Yanıtınız için teşekkürler, daha dikkatli okumam gerekiyor. UDP ve TCP'nin bir arada var olabileceğini zaten yazdınız .
Kurt

47

Prensip olarak, hayır.

Taşla yazılmamıştır; ancak tüm API'ların yazılma şekli: uygulama bir bağlantı noktası açar, bir tanıtıcı alır ve istemci bağlantısı (veya UDP durumunda bir paket) geldiğinde işletim sistemi bunu (bu tanıtıcı aracılığıyla) bildirir.

İşletim sistemi iki uygulamanın aynı bağlantı noktasını açmasına izin verdiyse hangisine bildirim gönderileceğini nasıl bilebilir?

Ama ... bunun etrafında yollar var:

  1. Jed'in belirttiği gibi , bağlantı noktasını gerçekten dinleyen ve diğerlerini bilgilendiren tek kişi olan 'ana' işlem yazabilirsiniz, istemci isteklerini ayırmak istediği mantığı kullanarak.
    • Linux ve BSD'de (en azından), ağlarla ilgili ölçütlere (belki menşe ağına veya bazılarına) göre paketleri 'görünür' bağlantı noktasından farklı uygulamalara (uygulamaların dinlediği yerlerde) yönlendiren 'yeniden eşleme' kuralları ayarlayabilirsiniz. basit yük dengeleme biçimleri).

37
iptables -m statistic --mode random --probability 0.5eğlencelidir.
Jed Smith

1
"Bir bağlantı noktası açar" ifadesinin tam anlamı nedir? Cümleyi anlıyorum, ancak bir port açıp idare ettiğinde sistemin tam olarak ne yaptığını biliyor musunuz? TCP ile bir bağlantı noktası açmak istediğinizde, bir akış aldığınızı ve bu akışın uzaktan kumanda ile bağlantınız olduğunu biliyorum, ancak web'de arama yapıyorum ve çok iyi bir açıklama bulamadım.
Samuel

4
@Samuel: bir bağlantı noktasını açmak (sunucu modunda) bir dosya tanımlayıcı almak anlamına gelir ve sistem bu bağlantı noktası numarasına bir SYN paketi aldığında, SYN + ACK ile yanıt verir ve ilişkili dosya tanımlayıcısında bir olay oluşturur. uygulama bu olaya belirli bir akışla ilişkilendirilmiş yeni bir dosya tanımlayıcısı oluşturan ve orijinal sunucu tanımlayıcısını istemcilerden yeni bağlantılar almak için serbest bırakan bir accept () çağrısı ile yanıtlar
Javier

7
Bu cevap doğru kabul edilemez. Tamamen hem SO_REUSEADDR hem de SO_REUSEPORT'un varlığına bakmaktadır.
Lorne Marquis

@Javier Hayır değil. Bir bağlantı noktasını sunucu uygulamasının bakış açısıyla açmak, dinleme soketini bağladığınız veya daha sonra açık olduğunuz soketi bağladığınızda listen()gerçekleşir. Muhtemelen soru, güvenlik duvarında açmakla ilgilidir. Burada çok fazla hata var ve hepsi 7 yıl içinde düzeltilmedi. Yanıt, aynı bağlantı noktası numarasına sahip farklı yerel adreslere bağlanma durumunu da atlar. Aslında tamamen yanlış.
Lorne Marquis

27

Evet, kesinlikle . Hatırladığım kadarıyla Çekirdek 3.9 sürümünden (sürümde emin değilim) itibaren destek desteği SO_REUSEPORTverildi. SO_RESUEPORTilk sunucu soketini bağlamadan önce bu seçeneği ayarladığı sürece, aynı bağlantı noktasına ve adrese bağlanmaya izin verir.

Hem için çalışır TCP ve UDP . Daha fazla ayrıntı için bağlantıya bakın: SO_REUSEPORT

Not : Kabul edilen cevap benim görüşüme göre artık geçerli değil.


2
Tamamıyla doğru. Doğru değilse, Wireshark nasıl çalışabilir?
Staszek

5
@Staszek Wireshark bağlantı noktalarını dinlemiyor. Paket seviyesinde çalışır.
Lorne

Oh, bu mantıklı olurdu. Her neyse, iki bağlantı noktasını 2 uygulama ile dinlemek kesinlikle mümkün.
Staszek

18

Hayır. Bir kerede yalnızca bir uygulama bir bağlantı noktasına bağlanabilir ve bağlama zorlanmışsa davranış belirsizdir.

İstediğinizin yakınında hiçbir yere benzemeyen çok noktaya yayın soketleriyle, her soketin seçeneklerinde SO_REUSEADDR ayarlandığı sürece birden fazla uygulama bir bağlantı noktasına bağlanabilir.

Bunu, tüm bağlantıları kabul eden ve işleyen bir "ana" işlem yazarak ve ardından aynı bağlantı noktasını dinlemesi gereken iki uygulamanıza dağıtabilirsiniz. Web sunucularının ve bu yaklaşımın benimsediği yaklaşım budur, çünkü birçok işlem 80'i dinlemelidir.

Bunun ötesinde, spesifikasyonlara giriyoruz - hem TCP hem de UDP'yi etiketlediniz, değil mi? Ayrıca, hangi platform?


her ikisi de beni ilgilendiriyor. Platform pencerelerdir, ancak cevap Linux için
farklıysa

8
Çok noktaya yayın soketi diye bir şey yoktur. UDP soketleri var. Çok noktaya yayın SO_REUSEADDR için bir önkoşul değildir.
Lorne Marquis

3

Bir ağ arabirimi için bir bağlantı noktasını dinleyen bir uygulamanız olabilir. Bu nedenle:

  1. httpd uzaktan erişilebilir arayüzü dinleme, ör. 192.168.1.1:80
  2. dinleyen başka bir daemon 127.0.0.1:80

Örnek kullanım durumu httpdbir yük dengeleyici veya proxy olarak kullanmak olabilir .


3

Başka bir yol, dahili olarak "gerçek" hizmetin dinlediği başka bir bağlantı noktasına yönlendirdiği trafik türünü (ssh, https, vb.) Analiz eden bir bağlantı noktasında dinleme programı kullanmaktır.

Örneğin, Linux için, sslh: https://github.com/yrutschle/sslh


Pencerelerde böyle bir program var mı? Hem yerel IIS sunucumun hem de ActiveMQ aracının 443 numaralı bağlantı noktasını dinlemesi gerekiyor
Harvey Lin

3

Bir TCP bağlantısı oluşturduğunuzda, bir IP adresinin (kullandığınız protokole bağlı olarak v4 veya v6) ve bir bağlantı noktasının birleşimi olan belirli bir TCP adresine bağlanmanız istenir.

Bir sunucu bağlantıları dinlediğinde, çekirdeğe belirli bir IP adresini ve bağlantı noktasını, yani bir TCP adresini veya ana bilgisayarın IP adreslerinin her birinde (genellikle IP adresiyle belirtilen aynı bağlantı noktasını) dinlemek isteyebileceğini bildirebilir. 0.0.0.0), etkin bir şekilde farklı "TCP adresleri" bir sürü dinlediği (örneğin 192.168.1.10:8000, 127.0.0.1:8000vs.)

Hayır, aynı "TCP adresini" dinleyen iki uygulamanız olamaz, çünkü bir ileti geldiğinde, çekirdek hangi uygulamanın iletiyi vereceğini nasıl bilebilir?

Bununla birlikte, çoğu işletim sisteminde tek bir arabirimde birkaç IP adresi ayarlayabilirsiniz (örneğin, 192.168.1.10bir arabiriminiz 192.168.1.11varsa, ağda başka kimse kullanmıyorsa da ayarlayabilirsiniz ) ve bu gibi durumlarda 8000bu iki IP adresinin her birinde bağlantı noktasını dinleyen ayrı uygulamalar olabilir .


2

Uzak IP'lerden en az biri zaten bilinen, statik ve yalnızca uygulamalarınızdan biriyle konuşmaya adanmışsa, gelen trafiği bu adresten "paylaşılan" yerel bağlantı noktasına yönlendirmek için iptables kuralını (tablo nat, zincir PREROUTING) kullanabilirsiniz. uygun uygulamanın gerçekten dinlediği diğer herhangi bir bağlantı noktası.


1

Evet ve hayır. Bir bağlantı noktasını yalnızca bir uygulama aktif olarak dinleyebilir. Ancak bu uygulama başka bir süreçle olan bağlantısını alt edebilir. Böylece aynı bağlantı noktasında çalışan birden çok işleminiz olabilir.


@trusktr, Ne demek düşünüyorum bu
warvariuc


0

Eğer uygulamalar ile birden fazla işlem demek istiyorsanız evet ama genellikle HAYIR. Örneğin Apache sunucusu aynı bağlantı noktasında (genellikle 80) birden çok işlem çalıştırır.


0

İki uygulamanın aynı bağlantı noktasını aynı ağ arabiriminde dinlemesini sağlayabilirsiniz.

Belirtilen ağ arabirimi ve bağlantı noktası için yalnızca bir dinleme soketi olabilir, ancak bu soket birkaç uygulama arasında paylaşılabilir.

Bir uygulama işleminde bir dinleme soketiniz varsa ve forkbu işlem varsa, soket devralınır, dolayısıyla teknik olarak aynı bağlantı noktasını dinleyen iki işlem olacaktır.


0

Aşağıdaki ile denedim socat:

socat TCP-L:8080,fork,reuseaddr -

Ve sokete bir bağlantı yapmamış olmama rağmen, reuseaddrseçeneğe rağmen aynı portta iki kez dinleyemiyorum .

(Daha önce beklediğim) bu mesajı alıyorum:

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

0

Sadece @jnewton'un bahsettiklerini paylaşmak için. Mac bilgisayarımda bir nginx ve gömülü tomcat işlemi başlattım. Her iki işlemin de 8080'de çalıştığını görebiliyorum.

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

-2

Kısa cevap:

Burada verilen cevaba göre . Aynı IP adresini ve bağlantı noktası numarasını dinleyen iki uygulamanız olabilir, bu nedenle bağlantı noktasından biri UDP bağlantı noktası, diğeri ise TCP bağlantı noktasıdır.

Açıklama:

Bağlantı noktası kavramı, TCP / IP yığınının taşıma katmanıyla ilgilidir, bu nedenle yığının farklı taşıma katmanı protokollerini kullandığınız sürece, aynı <ip-address>:<port>kombinasyonu dinleyen birden çok işleminiz olabilir .

İnsanların sahip olduğu bir şüphe, iki uygulamanın aynı <ip-address>:<port>kombinasyon üzerinde çalışıp çalışmadığıdır, uzak makinede çalışan bir istemci bu ikisi arasında nasıl ayrım yapar? IP katmanı paket başlığına ( https://en.wikipedia.org/wiki/IPv4#Header ) bakarsanız, protokol tanımlamak için 72 ila 79 arasındaki bitlerin kullanıldığını göreceksiniz, ayrım bu şekilde yapılabilir.

Bununla birlikte, aynı TCP <ip-address>:<port>kombinasyonunda iki uygulama olmasını istiyorsanız , yanıt hayırdır (İlginç bir alıştırma iki VM başlatacak, onlara aynı IP adresini, ancak farklı MAC adreslerini verecektir ve ne olduğunu görün - bazı zamanlar fark edeceksiniz VM1 paketleri alacak ve diğer zamanlarda VM2 paketleri alacak - ARP önbellek yenilemesine bağlı olarak).

İki uygulamanın aynı şekilde çalışmasını <op-address>:<port>sağlayarak bir tür yük dengeleme yapmak istediğinizi hissediyorum . Bunun için uygulamaları farklı bağlantı noktalarında çalıştırabilir ve aralarındaki trafiği birbirinden ayırmak için IP tablosu kuralları yazabilirsiniz.

Ayrıca @ user6169806'nın cevabına bakınız.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.