W moim głównym wątku mam while(listening)
pętlę, która wywołuje accept()
mój obiekt ServerSocket, a następnie uruchamia nowy wątek klienta i dodaje go do kolekcji, gdy nowy klient jest akceptowany.
Mam również wątek administratora, którego chcę używać do wydawania poleceń, takich jak „exit”, co spowoduje zamknięcie wszystkich wątków klienta, zamknięcie się i zamknięcie głównego wątku, ustawiając słuchanie na false.
Jednak accept()
wywołanie w while(listening)
pętli blokuje się i wydaje się, że nie ma sposobu, aby je przerwać, więc warunek while nie może być ponownie sprawdzony, a program nie może wyjść!
Czy jest lepszy sposób na zrobienie tego? Albo jakiś sposób na przerwanie metody blokowania?
java
networking
blocking
interrupt
lukeo05
źródło
źródło
Odpowiedzi:
Możesz zadzwonić
close()
z innego wątku, aaccept()
wywołanie wyrzuci plikSocketException
.źródło
close()
, mam na myśli, że wyrzuci wyjątek podczas robienia tego, więc czy istnieje inny sposób (który nie zgłasza wyjątku, również nie jest oparty na limicie czasu), aby zatrzymać nasłuchiwanie żądań?readLine()
zwróci wtedy wartość null i wystąpią normalne operacje zamykania, które wątek powinien już mieć na miejscu.Ustaw limit czasu na
accept()
, a połączenie wyłączy blokowanie po określonym czasie:http://docs.oracle.com/javase/7/docs/api/java/net/SocketOptions.html#SO_TIMEOUT
źródło
Dzwoni
close()
naServerSocket
opcję?http://java.sun.com/j2se/6/docs/api/java/net/ServerSocket.html#close%28%29
źródło
Możesz po prostu utworzyć gniazdo "void" dla przerwania serwera server.accept ()
Po stronie serwera
Metoda przerwania cyklu serwera
źródło
Przyczyną
ServerSocket.close()
zgłaszania wyjątku jest to, że masz dołączoneoutputstream
lubinputstream
dołączone do tego gniazda. Możesz bezpiecznie uniknąć tego wyjątku, najpierw zamykając strumienie wejściowe i wyjściowe. Następnie spróbuj zamknąćServerSocket
. Oto przykład:Możesz wywołać tę metodę, aby zamknąć dowolne gniazdo z dowolnego miejsca bez uzyskiwania wyjątku.
źródło
ServerSocket
ale do aSocket
i mówimy o zamykaniuServerSocket
not theSocket
, więcServerSocket
można je zamknąć bez zamykaniaSocket
strumieni a.Użyj serverSocket.setSoTimeout (timeoutInMillis) .
źródło
OK, mam to działające w sposób, który bardziej bezpośrednio odpowiada na pytanie PO.
Czytaj dalej obok krótkiej odpowiedzi, aby zobaczyć przykładowy wątek, w jaki sposób tego używam.
Krótka odpowiedź:
Przykład z prawdziwego świata:
W tym przykładzie mam ServerSocket oczekujący na połączenie wewnątrz Thread. Kiedy zamykam aplikację, chcę zamknąć wątek (a dokładniej gniazdo) w czysty sposób, zanim pozwolę aplikacji zamknąć, więc używam .setSoTimeout () na ServerSocket, a następnie używam wyrzucanego przerwania po upływie limitu czasu, aby sprawdzić, czy rodzic próbuje zamknąć wątek. Jeśli tak, to ustawiam zamknięcie gniazda, następnie ustawiam flagę wskazującą, że wątek jest zakończony, a następnie wychodzę z pętli Threads, która zwraca wartość null.
Następnie w mojej klasie kontrolera ... (pokażę tylko odpowiedni kod, wmasuję go we własny kod w razie potrzeby)
Mam nadzieję, że to pomoże komuś w dalszej drodze.
źródło
Inną rzeczą, którą możesz wypróbować, która jest czystsza, jest sprawdzenie flagi w pętli accept, a następnie, gdy twój wątek administratora chce zabić blokowanie wątku na akceptacji, ustaw flagę (uczyń go bezpiecznym dla wątku), a następnie utwórz gniazdo klienta podłączenie do gniazda nasłuchowego. Akceptacja przestanie blokować i zwróci nowe gniazdo. Możesz wypracować prosty protokół, który mówi wątkowi nasłuchującemu, aby czysto wychodził z wątku. A następnie zamknij gniazdo po stronie klienta. Bez wyjątków, dużo czystsze.
źródło