TIME_WAIT içindeki bir soketi zorla kapatmak nasıl?


113

Linux üzerinde bazen çöktüğü belli bir program çalıştırıyorum. Ondan hemen sonra açarsanız, ilk kez olduğu gibi 49200 yerine 49201 soketini dinler. netstat, 49200’ün TIME_WAIT durumunda olduğunu gösteriyor.

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


1
Eğer nedeniyle burada ise "çok fazla TIME_WAITsunucuda" , sadece içinden atlamak bunu cevaplamak yerine soru önlemek ilk üç cevaplar.
Pacerier

Yanıtlar:


148
/etc/init.d/networking restart

Ayrıntılı çalışmama izin verin. İletim Denetimi Protokolü (TCP) iki uç nokta (programlar) arasında iki yönlü, düzenli ve güvenilir bir veri iletim protokolü olacak şekilde tasarlanmıştır. Bu bağlamda, güvenilir terimi, ortasında kaybolursa paketleri yeniden ileteceği anlamına gelir. TCP, eşlerden alınan tek bir veya bir dizi paket için Onay (ACK) paketlerini geri göndererek güvenilirliği garanti eder.

Bu, sonlandırma isteği / yanıtı gibi kontrol sinyalleri için aynıdır. RFC 793 , TIME-WAIT durumunu aşağıdaki gibi tanımlar:

TIME-WAIT - uzaktaki TCP'nin bağlantı sonlandırma isteğinin onayını aldığından emin olmak için yeterli zamanın geçmesini bekler.

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

TCP, iki yönlü bir iletişim protokolüdür, bu nedenle bağlantı kurulduğunda, istemci ile sunucu arasında bir fark yoktur. Ayrıca, biri çıkışlardan birini arayabilir ve her iki eşin de kurulan bir TCP bağlantısını tamamen kapatmak için kapanmaya karar vermesi gerekir.

Çıkmayı aktif olarak daha yakın, diğeri pasif olarak daha yakın olanı arayalım. Aktif yaklaştırıcı FIN gönderdiğinde, durum FIN-WAIT-1’e gider. Daha sonra gönderilen FIN için bir ACK alır ve durum FIN-WAIT-2'ye gider. FIN'ı pasif yakından da aldığında, aktif olan yakın ACK'yı FIN'a gönderir ve durum TIME-WAIT'e gider. Pasif yakınlaştırıcı ACK'yı ikinci FIN'a almadıysa, FIN paketini tekrar iletir.

RFC 793 , TIME-OUT ürününü Maksimum Segment Ömrü'nün iki katı veya 2MSL olacak şekilde ayarlar. MSL, bir paketin İnternet'te dolanabileceği maksimum süre 2 dakikaya ayarlandığı için, 2MSL 4 dakikadır. Bir ACK'ya ACK olmadığından, aktif yakınlayıcı, pasif göndericinin ACK'yı FIN'ına almamış olması durumunda, doğru TCP / IP protokolüne uyması durumunda 4 dakika beklemekten başka bir şey yapamaz (teorik olarak) .

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

Soruyu cevaplamak için , TIME_WAIT içindeki bir soketi zorla nasıl kapatabilirim?

/etc/init.d/networking restart

Pratik olarak konuşursak, WMR'ın bahsettiği gibi SO_REUSEADDR seçeneğini kullanarak TIME-WAIT durumunu görmezden gelir. SO_REUSEADDR tam olarak ne yapar?

Bu soket seçeneği çekirdeğe, bu bağlantı noktası meşgul olsa bile (
TIME_WAIT durumunda) devam edip yeniden kullanabileceğini söyler. Meşgulse, ancak başka bir durumda, halen kullanımda olan bir adresi almaya devam edersiniz. Sunucunuz kapatılmışsa ve yuvalar hala bağlantı noktasında etkinken hemen yeniden başlatılmışsa yararlıdır. Beklenmeyen bir veri girerse, sunucunuzu şaşırtabileceğini, ancak bu mümkün olsa da, bunun mümkün olmadığını unutmayın.


8
Harika cevap, ancak sorunun doğru cevabı değil. Ağın yeniden başlatılması işe yarayacaktır, ancak o zaman yeniden başlatılması işe yarayacaktır, bu yüzden bu doğru olamaz.
Chris Huang-Leaver

3
@ Chris Huang-Leaver, soru şu: Bu soketi TIME_WAIT durumundan çıkarmaya hemen zorlamak için çalıştırabileceğiniz bir program var mı? yeniden başlatma bir programın çalıştırılması olarak düşünülebilirse, o zaman da doğru cevap olacaktır. Sence neden bu doğru olamaz?
Eugene Yokota

8
WMR en yararlı cevaba sahiptir (bu tür bir sorunla karşılaştığımda ne yaparım). Ağı yeniden başlatmak çözüm için fazla zorlayıcı değildir 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- Lea

6
oh tamam, bir dahaki sefere bazı işlemler SIGTERM'e takılıyor, onu düzeltmek yerine bilgisayarımı parçalayacağım.
Longpoke,

Bunun genelleştirilmesi "ağ servislerini yeniden başlat" dır. Belirli bir yer /etc/init.d/networkingplatforma özgüdür (Debian?) Bu nedenle kesin komut satırı diğer sistemler için farklı olacaktır (bazen oldukça radikal şekilde). Diğer yorumcularla, bunun aşırı derecede fazla kilolu göründüğü ve ilgisiz herhangi bir ağ hizmeti için açıkça rahatsız edici göründüğü konusunda hemfikirim.
üçlü

51

Çalıştırdığınız o programın kaynak koduna sahip olup olmadığınızı bilmiyorum, ancak eğer öyleyse setsockopt(2)soket TIME_WAIT durumunda olsa bile aynı yerel adrese bağlanmanıza olanak sağlayan SO_REUSEADDR ayarını yapabilirsiniz . soket aktif olarak dinliyor, bakınız socket(7)).

TIME_WAIT durumu hakkında daha fazla bilgi için Unix soket SSS bölümüne bakın .


ama zaten bağlı hatayı alamadım. Programı tekrar çalıştırdığımda (123456) yazısını dinliyor. Ayrıca sistemin bu port için TIME_WAIT gösterdiğini ancak hala bağlanabileceğimi görebiliyorum. neden?
Jayapal Chandran

2
SO_REUSEADDR ile bile, "Adres zaten kullanımda" hatası almak mümkündür. Detaylar için hea-www.harvard.edu/~fine/Tech/addrinuse.html adresine bakın .
Jingguo Yao,

@WMR SO_REUSEADDRbir soketi "kapatmaz". Sadece önceden açılmış olanları tekrar kullanmanızı sağlar. Öyleyse soru hala "Nasıl bir soketi zorla kapatabilirim TIME_WAIT?"
Pacerier

Bu doğru cevap, ancak soru tamamen doğru değildi. En azından sorunumu iyi çözdüm (diğer tüm bağlantıları da keserek tüm ağı yeniden başlatmak gibi değil).
V-Mark

SO_REUSEADDRdevam etmesine izin verecek bind(); ama o zaman bu soketi dinlemek istiyorsanız , aynı listen()şekilde dönecektir EADDRINUSE. Başka bir deyişle, bu cevap geçici yazılımları kullanan istemci yazılımına yardımcı olabilir, ancak sunucu yazılımı için sorunu çözmez.
Will

33

Bildiğim kadarıyla, programınıza daha iyi bir sinyal işleyicisi yazmak dışında soketi zorla kapatmanın bir yolu yoktur, ancak zaman aşımının ne kadar süreceğini 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

hangi TIME_WAIT soketlerinin yeniden kullanılıp kullanılamayacağını kontrol eder (muhtemelen zaman aşımı olmadan).

Bu arada, çekirdek belgeleri 'teknik uzmanların önerileri / talepleri' olmadan bu değerlerden hiçbirini değiştirmemeniz konusunda sizi uyarır. Ben değilim.

Program, 49200 numaralı bağlantı noktasına bağlanmayı denemek ve daha sonra bağlantı noktası kullanımdaysa, 1 artırmak için yazılmalıdır. Bu nedenle, kaynak kodun kontrolünü elinizde tutarsanız, bu davranışı birkaç saniye bekleyecek şekilde değiştirebilir ve artış yapmak yerine aynı bağlantı noktasında tekrar deneyebilirsiniz.


İkinci iki örneğin s / rw / tw / düzenleme yapması gerektiğini düşünüyorum, ancak yeterli temsilci bulunmuyor.

1
Çekirdek dokümantasyonundan alınmıştır: Dikkat! Hem tcp_tw_recycle hem de tcp_tw_reuse, sorunlara neden olabilir. Parametrenin etkinleştirildiği düğüm tarafından kullanılan veya kullanılan düğüm (ler) arasındaki ağ topolojisini anlamadan hiçbirini etkinleştirmemelisiniz. Güvenlik duvarı, NAT veya yük dengeleyici gibi TCP bağlantı durumlarının farkında olan düğümlerden geçen bağlantılar ayar nedeniyle kareleri düşürmeye başlayabilir. Sorun yeterince büyük sayıda bağlantı olduğunda ortaya çıkacaktır.

1Gelecekteki bağlantılar için işe yarayacak şekilde ayarlanmış , peki ya halihazırda açılan şu anki olanlar?
Pacerier

18

Aslında bir bağlantıyı öldürmenin bir yolu var - killcx . Bağlantının herhangi bir durumunda çalıştığını iddia ediyorlar (ki bu doğrulamadım). İletişimin gerçekleştiği arayüzü bilmeniz gerekir, varsayılan olarak eth0 varsayar.

GÜNCELLEME: Başka bir çözüm, bazı linux dağıtımlarının depolarına giren bir kesicidir .


3

Başka bir seçenek de SO_LINGER seçeneğini 0 zaman aşımı süresiyle kullanmaktır. Bu şekilde, soketi kapattığınızda zorla kapatılır ve FIN / ACK kapanma davranışına girmek yerine RST gönderilir. Bu, TIME_WAIT durumundan kaçınır ve bazı kullanımlar için daha uygun olabilir.


2
Aynı zamanda hala geçiş halindeki giden verileri kaybeder ve diğer ucunda bir hataya neden olabilir. Tavsiye edilmez.
user207421 31:11

@EJP Erken başarısızlık neredeyse her zaman doğru çağrıdır. Ağ kurma güvenilir değildir ve bununla savaşmak işleri yavaşlatacaktır. Düşen bir uygulama, herhangi bir verinin güvenli bir şekilde gerçekleştirildiğini varsayamaz.
Tobu

1
Aslında, diğer uç nokta, TCP üzerinden kendi uygulama katmanı güvenilir taşımasını gerçekleştiren, gömülü endüstriyel veri yolu ağ geçidi olduğunda, söz konusu taşımacılığın RST almadığı ve böylece dolmadığı sürece bağlantının kapanmasını önlediği, her gün bunu tavsiye ederim. bu ağ geçidindeki bağlantı sınırı. Orada. Size ne yazık ki böyle bir saldırıya başvurmayı gerektiren çok özel ve çok gerçek bir örnek verdim.
andyn

@ Tobu Ağ iletişimi güvenilir değildir, ancak TCP olmaya çalışır ve bunu daha da kötüye götürmek daha iyi bir şey yapmayı gerektirmez ve TCP'nin işini yapmasına izin vermek hiçbir şeyle 'savaşmak' anlamına gelmez.
user207421 22:18

2

Alternatif bir çözüm, 49200 numaralı bağlantı noktasını dinleyen bazı güvenilir proxy veya bağlantı noktası iletme yazılımına sahip olmak, ardından bağlantıyı farklı bağlantı noktaları kullanarak daha az güvenilir programınızın birkaç örneğinden birine iletmek olabilir ... HAPROXY akla gelir.

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


0

TIME_WAIT, soket programlama istemci sunucusu mimarisinde en sık rastlanan sorundur. Bunun için en iyi çözüm, düzenli aralıklarla birkaç saniye bekleyin. Gerçek zamanlı uygulamalar için sunucuya ihtiyaç duydukları anda hemen kalkmalılar. SO_REUSEADDR seçeneği var.

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.