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ı?
/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:
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.
Ç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.
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.
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.
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.
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.
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.