2011-01-12 14 views
14

Buduję aplikację, która nasłuchuje zarówno na TCP, jak i UDP, i mam problem z moim mechanizmem zamykania. Kiedy zadzwonię pod numer Thread.interrupt() na każdym z wątków nasłuchujących, wątek TCP zostanie przerwany ze słuchania, podczas gdy słuchacz UDP nie jest. Aby być konkretnym, wątek TCP używa ServerSocket.accept(), który po prostu zwraca (bez faktycznego łączenia). Podczas gdy wątek UDP używa DatagramSocket.receive() i nie wychodzi z tej metody.Przerwanie wątku w DatagramSocket.receive

Czy jest to problem występujący w moim środowisku JRE, systemie operacyjnym lub czy powinienem przejść na numer (Datagram)Socket.close()?

AKTUALIZACJA: Znalazłem analysis problemu. Potwierdza, że ​​zachowanie nie jest spójne.

+0

Tylko po to, aby pomóc komukolwiek zajmującemu się tym samym problemem: Moje 'ServerSocket.accept()' nie powróciło bez połączenia. Wracał, ponieważ moja przeglądarka (FF4b10) żąda favikonu 3 razy. Jedno z żądań wywołało test Thread.interrupted(). Przejdę do trybu 'close()'. – SEK

Odpowiedz

26

Powszechnym idiomem dla przerywania pracy sieciowej jest zamknięcie kanału. Byłoby to dobre rozwiązanie, gdybyś musiał skutecznie je przerwać, czekając na wysłanie lub odebranie.

public class InterruptableUDPThread extends Thread{ 

    private final DatagramSocket socket; 

    public InterruptableUDPThread(DatagramSocket socket){ 
     this.socket = socket; 
    } 
    @Override 
    public void interrupt(){ 
    super.interrupt(); 
    this.socket.close(); 
    } 
} 
+0

Nie mogłem sam tego lepiej napisać. Dzięki! – SEK

0

DatagramSocket.receive blokuje do momentu otrzymania datagramu. Prawdopodobnie musisz użyć setSoTimeout, aby ustawić limit czasu.

+0

Limit czasu nie jest dopuszczalnym rozwiązaniem w tym przypadku. Również 'DatagramSocket.receive()' powinno zostać przerwane, dlatego jest to dziwne. – SEK

+1

@SEK: nie, nie powinno. W Javadoc nie ma nic, co by to sugerowało. Jeśli chcesz zachować możliwość przerywania, musisz użyć DatagramChannel, który implementuje InterruptibleChannel. – EJP

2

Z tego co wiem, close() jest właściwym sposobem przerwania zablokowanego gniazda. Przerwanie i pozostawienie otwartego czegoś, co mogło już zrobić częściowy odczyt lub zapis, sprawia, że ​​rzeczy stają się niepotrzebnie skomplikowane. Łatwiej jest tylko radzić sobie z wynikiem "sukcesu" lub "rezygnacji".