Soru TIME_WAIT'de bir soketi zorlayarak nasıl takabilirsiniz?


Bazen çökmekte olan linux üzerinde belirli bir program çalıştırıyorum. Bundan sonra hızlı bir şekilde açarsanız, ilk kez yaptığı gibi 49200 yerine 49200'ü dinler. netstat, 49200'ün TIME_WAIT durumunda olduğunu ortaya çıkardı.

Bu soketin TIME_WAIT durumundan çıkmasını hemen zorlamak için çalıştırabileceğiniz bir program var mı?


109
2017-09-03 12:57


Menşei


Eğer burada olursanız "çok fazla TIME_WAIT sunucuda "sadece geçmek Cevaplamak yerine, sorudan kaçınan ilk üç cevap. - Pacerier


Cevaplar:


/etc/init.d/networking restart

Detaylandırmama izin ver. Transmission Control Protocol (TCP), iki uç nokta (program) arasında çift yönlü, düzenli ve güvenilir bir veri aktarım protokolü olarak tasarlanmıştır. Bu bağlamda, güvenilir terim, ortada kaybolursa paketlerin yeniden iletileceği anlamına gelir. TCP, Aktarım (ACK) paketlerini eşlerden gelen tek veya çok sayıda paket için geri göndererek güvenilirliği garanti eder.

Bu, sonlandırma talebi / yanıtı gibi kontrol sinyalleri için de geçerlidir. RFC 793 TIME-WAIT durumunu aşağıdaki gibi tanımlar:

TIME-WAIT - beklemeyi temsil ediyor   emin olmak için geçmek için yeterli zaman       Uzak TCP bağlantısının onayını aldı       sonlandırma talebi.

Aşağıdaki TCP durum şemasına bakın: alt text

TCP iki yönlü bir iletişim protokolüdür, bu nedenle bağlantı kurulduğunda, istemci ve sunucu arasında bir fark yoktur. Ayrıca, her ikisi de sonlandırmaları çağırabilir ve her iki taraf da kurulu bir TCP bağlantısını tamamen kapatmak için kapanışta anlaşmalıdır.

İlk olarak, aktif kapanış olarak çıkışları ve diğeri pasif olanı daha yakına çağır. Aktif kapatıcıyı FIN gönderdiğinde, durum FIN-WAIT-1'e gider. Ardından gönderilen FIN için bir ACK alır ve durum FIN-WAIT-2'ye gider. Pasif kapatıcıdan da FIN'yi aldıktan sonra, aktif kapatıcı ACK'yı FIN'ye gönderir ve durum TIME-WAIT konumuna geçer. Pasif yakın ACK'yı ikinci FIN'ye almadığı takdirde, FIN paketini yeniden iletecektir.

RFC 793 TIME-OUT değerini Maksimum Segment Yaşam Süresi veya 2MSL'nin iki katı olacak şekilde ayarlar. MSL'den bu yana, bir paketin İnternet'te dolaşabileceği maksimum süre 2 dakikaya ayarlanır, 2MSL 4 dakikadır. Bir ACK'ye ACK olmadığından, aktif kapatıcı, pasif göndericinin ACK'yı kendi FIN'ına (teorik olarak) almadığı durumda, TCP / IP protokolüne doğru şekilde uyması halinde 4 dakika beklemek için hiçbir şey yapamaz. .

Gerçekte, eksik paketler muhtemelen nadirdir ve hepsi LAN içinde veya tek bir makine içinde gerçekleşiyorsa çok nadirdir.

Soruya cevap vermek için nasıl yapılır? zorla TIME_WAIT içinde bir soket kapatın, hala orijinal yanıtıma bağlı kalacağım:

/etc/init.d/networking restart

Pratik olarak, programlayacağım, bu yüzden WMR'dan bahsedildiği gibi SO_REUSEADDR seçeneğini kullanarak TIME-WAIT durumunu yok sayar. SO_REUSEADDR tam olarak ne yapar?

Bu soket seçeneği çekirdeğe söyler   Bu bağlantı noktası meşgul olsa bile (
  TIME_WAIT durumu) devam edin ve   Yine de onu tekrar kullan. Meşgulse ama   başka bir devletle, hala alacaksın   kullanımda bir adres hatası var. O   sunucunuz kapatılmışsa yararlıdır   aşağı ve hemen yeniden başlatıldı   Soketler hala üzerinde aktif iken   Liman. Farkında olmalısınız eğer   Beklenmeyen herhangi bir veri geliyor, olabilir   sunucunuzu karıştırmayın, ancak bu sırada   Mümkün değil.


139
2017-09-03 13:11



Büyük cevap, ama sorusuna doğru cevap değil. Ağın yeniden başlatılması işe yarayacaktı, ancak daha sonra yeniden başlatılacaktı, bu yüzden bu doğru olamaz. - Chris Huang-Leaver
@Chris Huang-Leaver, şu soru şu: “Bu soketin TIME_WAIT durumundan çıkmasını hemen zorlayabilecek bir program var mı?” Yeniden başlatma, bir programın çalıştırılması olarak düşünülebilirse, o zaman doğru bir cevap olacaktır. Bunun neden doğru olamayacağını düşünüyorsun? - Eugene Yokota
WMR en yararlı cevaba sahiptir (bu tür bir konuya girdiğimde yaptığım şey). Ağın yeniden başlatılması çözüm için çok zor ve zaman aşımını beklemekten daha uzun sürebilir. Sorusunun doğru cevabı 'Hayır', ancak SO iki harfli cevap yazmanıza izin vermez :-) - Chris Huang-Leaver
tamam, bir dahaki sefere SIGTERM üzerinde bir süreç askıda kalıyor, onu düzeltmek yerine bilgisayarımı parçalayacağım. - Longpoke


Çalıştığınız programın kaynak koduna sahip olup olmadığınızı bilmiyorum, ancak eğer öyleyse SO_REUSEADDR'yi setsockopt(2) soket TIME_WAIT durumunda olsa bile aynı yerel adrese bağlanmanıza izin verir (bu soket aktif olarak dinlemediyse, bkz. socket(7)).

TIME_WAIT durumu hakkında daha fazla bilgi için bkz. Unix soketi SSS.


50
2017-09-03 13:17



ama zaten bağlı olan hatayı almadım. programı tekrar çalıştırdığımda (123456) postu dinler. Sistemin bu port için TIME_WAIT olduğunu ancak yine de bağlanabileceğimi görebiliyorum. niye ya? - Jayapal Chandran
SO_REUSEADDR ile bile, "Kullanılmakta olan adres" hatasını almak hala mümkündür. Ayrıntılar için bakınız hea-www.harvard.edu/~fine/Tech/addrinuse.html. - Jingguo Yao
@WMR SO_REUSEADDR bir soketi "kapatmaz". Sadece açılmış olanları yeniden kullanmanıza olanak tanır. Yani soru hala "Nasıl bir soket içinde zorla kapatmak için TIME_WAIT?" - Pacerier


Bildiğim kadarıyla, soketin zorla kapatılmasının, programın içine daha iyi bir sinyal işleyicisi yazmanın dışında kalmasının bir yolu yoktur, fakat zaman aşımının ne kadar sürdüğünü kontrol eden bir / proc dosyası vardır. Dosya

/proc/sys/net/ipv4/tcp_tw_recycle

ve bunu yaparak zaman aşımını 1 saniyeye ayarlayabilirsiniz:

echo 1 > /proc/sys/net/ipv4/tcp_tw_recycle 

Ancak, bu sayfa Bu değişkeni ayarlarken olası güvenilirlik sorunları hakkında bir uyarı içerir.

Ayrıca ilgili bir dosya var

/proc/sys/net/ipv4/tcp_tw_reuse

TIME_WAIT soketlerinin yeniden kullanılabileceğini (muhtemelen herhangi bir zaman aşımı olmadan) kontrol eder.

Bu arada, çekirdek dokümantasyonu, bu değerlerden 'teknik uzmanların tavsiyeleri / talepleri olmadan' değiştirmemeye sizi uyarır. Ben öyle değilim.

Program 49200 numaralı bağlantı noktasına bağlanmayı denemek ve ardından bağlantı noktası zaten kullanılıyorsa 1'e yükseltmek için yazılmıştır. Bu nedenle, kaynak kodun denetimini elinizde tutarsanız, bu davranışı birkaç saniye bekleyerek değiştirebilir ve artırıp artırmak yerine aynı bağlantı noktasında tekrar deneyebilirsiniz.


32
2017-09-03 13:24



İkinci iki örnek s / rw / tw / olması gerektiğini düşünürdüm, ama yeterli rep eksik.
Çekirdek belgelerinden alınmıştır: Dikkat. Hem tcp_tw_recycle hem de tcp_tw_reuse sorunlara neden olabilir. Parametrenin etkin olduğu düğüm tarafından kullanılan veya kullanılan düğümler arasında ağ topolojisini anlamadan etkinleştirmemelisiniz. Güvenlik duvarı, NAT veya yük dengeleyici gibi TCP bağlantı durumlarının farkında olan düğümler aracılığıyla yapılan bağlantılar, ayar nedeniyle çerçeveyi düşürmeye başlayabilir. Yeterli sayıda bağlantı olduğunda sorun görünür olacaktır.
Olarak ayarlanıyor 1 Gelecek bağlantılar için çalışıyor, ama şu an açılmış olanlar hakkında ne dersiniz? - Pacerier


Aslında bir bağlantıyı öldürmenin bir yolu var. killcx. Herhangi bir bağlantı durumunda çalıştığını iddia ediyorlar (doğrulamadığım). İletişimin gerçekleştiği arayüzü bilmeniz gerekiyor, varsayılan olarak eth0 varsayılıyor gibi görünüyor.

GÜNCELLEME: başka bir çözüm kesici Bazı linux distros 'depolarında gelir.


16
2017-10-30 17:32



Teşekkürler! Bu yardımcı program harika çalışıyor! Uzun bir işi tekrar başlatmam için beni kurtardı. - Zanson


Diğer bir seçenek de, SO_LINGER seçeneğini 0 zaman aşımı ile kullanmaktır. Bu şekilde, soketi kapattığınızda zorla kapatılır, FIN / ACK kapanış davranışına girmek yerine bir RST gönderilir. Bu, TIME_WAIT durumunu engeller ve bazı kullanımlar için daha uygun olabilir.


3
2018-06-10 22:33



Ayrıca, hala geçiş halindeki giden verileri kaybeder ve diğer ucunda bir hataya neden olabilir. Tavsiye edilmez. - user207421
@EJP Erken başarısızlık hemen hemen her zaman doğru çağrıdır. Ağ güvenilir değildir ve bu, işleri yavaşlatır. Kilitlenen bir uygulama, herhangi bir verinin güvenli bir şekilde yapıldığını kabul edemez. - Tobu
Aslında, diğer son nokta, TCP üzerinden kendi uygulama katmanı güvenilir aktarımını uygulayan bir buggy, gömülü endüstriyel otobüs ağ geçidi olduğunda, bunu önerebilirim. Burada söz konusu taşıma, RST'yi almadıkça bağlantının her zaman kapanmasını önler ve böylece doldurur. Bu ağ geçidindeki bağlantı sınırı. Orada. Size çok özel ve çok gerçekçi bir örnek verdim, ne yazık ki böyle hacklere başvurmayı gerektiriyor. - andyn
@Tobu Networking güvenilir değil, ama TCP olmaya çalışıyor ve bu kötüyü daha iyi bir hale getirmeyi ve TCP'nin işini yapmasını sağlamayacak bir şey yapmıyor. - user207421


Alternatif bir çözüm, 49200 numaralı bağlantı noktasını dinleyen güvenilir bir proxy veya port yönlendirme yazılımına sahip olmak, ardından bağlantıyı farklı portlar kullanarak daha az güvenilir programınızın birkaç örneğinden birine iletmek olacaktır ... HAPROXY, akılda kalıcıdır.

Bu arada, bağlandığınız port oldukça yüksektir. 0-1024 aralığının hemen üstünde kullanılmayan bir deneyebilirsiniz. Sisteminizin geçici bağlantı noktası olarak daha düşük bir bağlantı noktası numarası kullanma olasılığı daha azdır.


2
2017-08-21 20:28





Soket programlama istemci sunucu mimarisinde TIME_WAIT en yaygın sorun. Periyodik olarak birkaç saniye bekleyin, bunun için en iyi çözümdür. Gerçek zamanlı uygulamalar için sunucunun hemen kalkması gerekiyor Onlar için SO_REUSEADDR seçeneği var.


0
2017-10-13 19:07