Soru SO_REUSEADDR (setsockopt seçeneği) - Linux'un anlamı nedir? [çift]


Bu sorunun zaten bir cevabı var:

Man sayfasından:

SO_REUSEADDR Kuralların olduğunu belirtir   sağlanan adreslerin doğrulanması için kullanılır   bağlama () yerel yeniden kullanımına izin vermelidir   adresleri destekliyorsa,   protokol. Bu seçenek int alır   değer. Bu bir Boole seçeneği

Ne zaman kullanmalıyım? Neden "yerel adreslerin yeniden kullanımı" verir?


44
2017-07-12 15:42


Menşei


Bu sorunun neden vc ++ etiketlendiğini anlamıyorum. - William Briand
Bir hata. C ++ 'yı kastetmiştim. Teşekkür ederim. - Ray Templeton
Hala C ++ ile ilgisi yok :) - Nikolai Fetissov


Cevaplar:


TCP'nin birincil tasarım hedefi, paket kaybı, paket yeniden sıralama ve - anahtar, burada - paket çoğaltması karşısında güvenilir veri iletişimine izin vermektir.

Bağlantı kurulurken bir TCP / IP ağ yığınının bununla ilgilenmesi oldukça açık, ancak bağlantı kapatıldıktan hemen sonra gerçekleşen bir kenar durumu var. Sohbetin sonunda gönderilen bir paket çoğaltılır ve geciktirilirse ne olur? 4 yönlü kapatma paketler gecikmeli paketten önce alıcıya mı geliyor? Yığın, bağlantıyı büyük ölçüde kapatır. Daha sonra, gecikmiş kopya paket gösterilir. Yığın ne yapmalı?

Daha da önemlisi, bu bağlantıya sahip olan program hemen ölürse ne yapmalı, o zaman aynı IP adresi ve TCP bağlantı noktası numarası isteyen başka bir kişi mi başlayacak?

Birkaç seçenek var:

  1. Bir paketin uçuşta olabileceği maksimum sürenin en az 2 katı kadar bu IP / bağlantı noktasının yeniden kullanılmasına izin verilmez. TCP'de, bu genellikle 2 × denirMSL gecikme. Bazen ayrıca 2 × görürsünüzRTTBu kabaca eşdeğerdir.

    Bu, tüm yaygın TCP / IP yığınlarının varsayılan davranıştır. 2 × MSL tipik olarak 30 ila 120 saniye arasındadır. (Bu TIME_WAIT Bu süre sonunda, yığın herhangi bir hileli paketin düştüğünü varsayar yolda süresinin dolması nedeniyle TTL'leri, yani bırakır TIME_WAIT devlet, IP / port combo'nun yeniden kullanılmasına izin veriyor.

  2. Yeni programın bu IP / port combo'ya yeniden bağlanmasına izin verin. İle yığınlarda BSD prizler arayüzler - aslında tüm Unixler ve Unix benzeri sistemler, artı Windows üzerinden Winsock - Bu davranışa SO_REUSEADDR üzerinden seçenek setsockopt() aramadan önce bind().

SO_REUSEADDR En çok sunucu programlarında ayarlanır.

Nedeni, ortak bir model, bir sunucu yapılandırma dosyasını değiştirmeniz ve yapılandırmayı yeniden yüklemesi için bu sunucuyu yeniden başlatmanız gerektiğidir. olmadan SO_REUSEADDR, bind() Yeniden başlatılan programın yeni örneğindeki çağrı, onu öldürdüğünüzde önceki örneğe açık bağlantılar varsa başarısız olur. Bu bağlantılar TCP portunu TIME_WAIT 30-120 saniye için devlet, bu yüzden yukarıdaki 1. duruma düşersiniz.

Yapılması gereken güvenli şey, TIME_WAITperiyod, ama pratikte bunu yapmaya değecek kadar büyük bir risk değildir. Gerekenden daha fazla gelen bağlantıyı kaçırmamak için sunucuyu hemen geri almak daha iyidir.


96
2017-07-12 23:18



Büyük ve çok yararlı bir cevap. Btw: aşağıdaki alıntı unutmayın adam 7 ip: Bağlanan bir TCP yerel soket adresi, kapatıldıktan sonra bir süre için kullanılamaz. SO_REUSEADDR bayrak ayarlandı. Bu bayrağı kullanırken TCP'yi daha az güvenilir hale getirirken dikkatli olunmalıdır.


SO_REUSEADDR sunucunuza izin verir   içindeki bir adrese bağla
  TIME_WAIT durumu.

Bu soket seçeneği, çekirdeğe bu bağlantı meşgul olsa bile (TIME_WAIT durumunda) devam edin ve yine de yeniden kullanın. Meşgulse, ancak başka bir durum varsa, hala kullanımda bir hata alırsınız. Sunucunuz kapatılmışsa ve yuvalar hala bağlantı noktasında etkinken, hemen yeniden başlatılır.

itibaren unixguide.net


19
2017-07-12 15:51



Çok teşekkürler, bunu da buldum ama hala anlamadım ... - Ray Templeton
Bir TCP bağlantısı açtığınızı varsayalım. Veri iletildikten sonra soketi kapatırsınız. Ama aslında, TIME_WAIT durumunda (TIME_WAIT == "olarak ayarlanacaktır, bazı veriler henüz teslim edilmemiş olabilir, ya da bir şey, bu yüzden bir süre için dikkatli bir TCP uygulaması olarak bekleriz :)"). Sadece REUSEADDR kullanarak aynı IP / bağlantı noktasına başka bir bağlantı açamazsınız. - William Briand
Kuruş düştü. Çok teşekkür ederim! - Ray Templeton


Bir soket oluşturduğunuzda, gerçekten sahip değilsiniz. İşletim Sistemi (TCP yığını) sizin için oluşturur ve ona erişmek için bir tanıtıcı (dosya tanıtıcısı) verir. Soketiniz kapalıyken, birkaç durumdan geçerken işletim sisteminin "tamamen kapatması" zaman alır. EJP'nin yorumlarda belirttiği gibi, en uzun gecikme genellikle TIME_WAIT durumundan kaynaklanmaktadır. Bu ekstra gecikme, sonlandırma sırasının sonundaki kenar durumlarını işlemek için gereklidir ve son sonlandırma onayının ya geçtiğinden ya da bir zaman aşımı nedeniyle diğer tarafın kendini sıfırladığından emin olun. Burada bulabilirsiniz Bu durum hakkında bazı ekstra düşünceler. Temel hususlar aşağıdaki gibi belirtilmiştir:

TCP'nin iletilen tüm verilerin teslim edileceğini garanti ettiğini unutmayın.   Eğer mümkünse. Bir soketi kapattığınızda, sunucu bir   TIME_WAIT durumu, tüm verilerin sahip olduğundan gerçekten emin olmak için   geçti. Bir soket kapalı olduğunda, iki taraf da göndererek kabul eder   birbirlerine daha fazla veri göndermeyecek mesajlar. Bu, bu   bana iyi görünüyordu ve el sıkışması bittikten sonra   soket kapalı olmalıdır. Sorun iki katlıdır. İlk önce, hayır   Son ack'in başarılı bir şekilde iletildiğinden emin olmanın yolu.   İkincisi, ağda kalan "solda dolaşan çiftler" olabilir.   Onlar teslim edilirse ele alınmalıdır.

Aynı ip: port çifti ile birden çok yuva oluşturmaya çalışırsanız, önceki yuva tam olarak serbest bırakılmayacağı için "kullanımda olan adresi" hatasını alırsınız. SO_REUSEADDR kullanımı, önceki hataların kontrollerini geçersiz kılacağından bu hatayı giderecektir.


6
2017-07-12 23:33



Bence bu ifade en önemli ve daha önce hiç bahsetmedi - "Aynı ip ile birden çok soket oluşturmaya çalışırsanız: port çifti gerçekten hızlıdır," kullanımda olan adresi "hatasını alırsınız." Bir oy verene kadar :) - ultimate cause
BT, işletim sisteminin bunu "fark etmesini" gerektirmiyor. Var tanımlı TCP durumu TCP protokolünün belirtildiği TIME_WAIT çağrıldı gerektirir Sonunda serbest bırakmadan önce limanı korumak için işletim sistemi. Bu durum, ilgili soketin kapanmasını tarihler. - user207421