Jak przymusowo zamknąć gniazdo w czasie oczekiwania?

Uruchamiam konkretny program na Linuksie, który czasami się zawiesza. Jeśli otworzysz go szybko po tym, nasłuchuje na socket 49201 zamiast 49200, jak to było za pierwszym razem. netstat ujawnia, że 49200 znajduje się w stanie TIME_WAIT.

Czy istnieje program, który można uruchomić, aby natychmiast wymusić przesunięcie gniazda poza stan TIME_WAIT?

Author: Rehan, 2008-09-03

7 answers

W rzeczywistości istnieje sposób na zabicie połączenia- killcx . Twierdzą, że działa w każdym stanie połączenia (którego nie zweryfikowałem). Musisz jednak znać interfejs, w którym odbywa się komunikacja, wydaje się, że domyślnie przyjmuje eth0.

Aktualizacja: innym rozwiązaniem jest cutter , który pojawia się w repozytoriach niektórych dystrybucji Linuksa.

 18
Author: akostadinov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-08 07:02:39
/etc/init.d/networking restart
Pozwól, że coś wyjaśnię. Transmission Control Protocol (TCP) - dwukierunkowy, uporządkowany i niezawodny protokół transmisji danych pomiędzy dwoma punktami końcowymi (programami). W tym kontekście termin niezawodny oznacza, że retransmituje PAKIETY, JEŚLI zagubi się w środku. TCP gwarantuje niezawodność poprzez odesłanie pakietów potwierdzających (ACK) z powrotem dla pojedynczego lub szeregu pakietów otrzymanych od peera. To samo dotyczy sygnałów sterujących, takich jak wniosek o wypowiedzenie/odpowiedź. RFC 793 definiuje stan oczekiwania w następujący sposób:

TIME-WAIT-oznacza oczekiwanie na wystarczająco dużo czasu, aby się upewnić zdalny TCP otrzymał potwierdzenie połączenia wniosek o wypowiedzenie umowy.

Patrz poniższy diagram stanu TCP: alt text

TCP jest dwukierunkowym protokołem komunikacyjnym, więc po nawiązaniu połączenia nie ma różnicy między Klientem a serwerem. Również, Albo można wywołać quits, i obaj rówieśnicy muszą zgodzić się na zamknięcie, aby w pełni zamknąć ustanowione połączenie TCP.

Nazwijmy pierwszego, który nazywa się aktywnym bliższym, a drugiego biernym bliższym. Gdy aktywny closer wysyła FIN, stan przechodzi do FIN-WAIT-1. Następnie otrzymuje ACK dla wysłanego FIN i stan przechodzi do FIN-WAIT-2. Gdy otrzymuje FIN również od biernego bliższego, aktywny bliższy wysyła ACK do FIN i stan przechodzi do CZAS-CZEKAJ. W przypadku, gdy pasywny bliższy nie otrzymał ACK do drugiej płetwy, retransmituje pakiet FIN.

RFC 793 ustawia TIME-OUT na dwukrotność maksymalnego czasu życia segmentu, czyli 2MSL. Ponieważ MSL, maksymalny czas, jaki pakiet może wędrować po Internecie, jest ustawiony na 2 minuty, 2MSL to 4 minuty. Ponieważ nie ma ACK do ACK, aktywny closer nie może nic zrobić, ale czekać 4 minuty, jeśli prawidłowo przylega do protokołu TCP / IP, na wypadek, gdyby pasywny nadawca nie otrzymał ACK do swojej płetwy (teoretycznie).

W rzeczywistości brakujące pakiety są prawdopodobnie rzadkie i bardzo rzadkie, jeśli wszystko dzieje się w sieci LAN lub na jednej maszynie.

Aby odpowiedzieć na pytanie dosłownie, jak forcibly zamknąć gniazdo w TIME_WAIT?, I tak będę trzymać się oryginalnej odpowiedzi:

/etc/init.d/networking restart

Praktycznie rzecz biorąc, zaprogramowałbym go tak, aby ignorował stan oczekiwania przy użyciu opcji SO_REUSEADDR, jak wspomniała WMR. co dokładnie robi SO_REUSEADDR do?

Ta opcja gniazda informuje jądro że nawet jeśli ten port jest zajęty (w
stan TIME_WAIT), śmiało i użyj go ponownie. Jeśli jest zajęty, ale z innym stanem, nadal dostaniesz adres już używany błąd. Informatyka jest przydatny, jeśli serwer został zamknięty w dół, a następnie ponownie uruchomiony od razu podczas gdy gniazda są nadal aktywne na jego port. Należy mieć świadomość, że jeśli wszelkie nieoczekiwane dane przychodzą, może mylić swoje serwer, ale podczas gdy to jest możliwe, nie jest prawdopodobne.

 157
Author: Eugene Yokota,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-08 18:00:44

Nie wiem, czy masz kod źródłowy tego konkretnego programu, który uruchamiasz, ale jeśli tak, możesz po prostu ustawić SO_REUSEADDR za pomocą setsockopt(2), co pozwala na bindowanie na tym samym lokalnym adresie, nawet jeśli gniazdo jest w stanie TIME_WAIT(chyba że gniazdo aktywnie nasłuchuje, zobacz socket(7)).

Aby uzyskać więcej informacji na temat stanu TIME_WAIT zobacz Unix socket FAQ.

 52
Author: WMR,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-03 13:17:07

Z tego, co wiem, nie ma sposobu na wymuszone zamknięcie gniazda poza zapisaniem lepszej obsługi sygnału do twojego programu, ale istnieje plik / proc, który kontroluje, jak długo trwa limit czasu. Plik

/proc/sys/net/ipv4/tcp_tw_recycle

I możesz ustawić timeout na 1 sekundę, wykonując to:

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

Jednakże ta strona zawiera ostrzeżenie o możliwych problemach z niezawodnością podczas ustawiania tej zmiennej.

Istnieje również powiązany plik

/proc/sys/net/ipv4/tcp_tw_reuse
Która kontroluje, czy Gniazda TIME_WAIT mogą być ponownie użyte (prawdopodobnie bez limitu czasu).

Nawiasem mówiąc, dokumentacja jądra ostrzega, aby nie zmieniać żadnej z tych wartości bez 'porad / próśb ekspertów technicznych'. A ja nie.

Program musi być napisany, aby spróbować połączyć się z portem 49200, a następnie zwiększyć o 1, jeśli port jest już używany. Dlatego, jeśli masz kontrolę nad kodem źródłowym, możesz zmienić to zachowanie, aby odczekać kilka sekund i spróbować ponownie na tym samym port, zamiast inkrementacji.

 34
Author: Leigh Caldwell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-03 13:24:42

Inną opcją jest użycie opcji SO_LINGER z limitem czasu 0. W ten sposób, po zamknięciu gniazda jest wymuszone zamknięcie, wysyłanie RST zamiast przechodzenia do zachowania zamykania FIN/ACK. Pozwoli to uniknąć stanu TIME_WAIT i może być bardziej odpowiednie dla niektórych zastosowań.

 3
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-10 22:33:36

Alternatywnym rozwiązaniem byłoby posiadanie niezawodnego oprogramowania proxy lub przekierowującego porty, które nasłuchuje na porcie 49200, a następnie przekazuje połączenie do jednej z kilku instancji mniej niezawodnego programu używającego różnych portów... Na myśl przychodzi HAPROXY.

Nawiasem mówiąc port, na którym się łączysz, jest dość wysoki. Możesz spróbować użyć nieużywanego tuż powyżej zakresu 0-1024. System rzadziej używa niższego numeru portu jako efemerycznego portu.

 2
Author: andrew pate,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-21 20:28:30

TIME_WAIT jest najczęstszym problemem w architekturze serwera klienta. Poczekaj kilka sekund, próbując okresowo jest najlepszym rozwiązaniem dla niego. W przypadku aplikacji w czasie rzeczywistym potrzebują serwera, który musi natychmiast wstać Istnieje dla nich opcja SO_REUSEADDR.

 0
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-10-13 19:07:51