2011-01-12 32 views
14

TCPとUDPの両方をリッスンするアプリケーションを構築していますが、シャットダウンメカニズムに問題があります。それぞれのリスニングスレッドでThread.interrupt()と呼ぶと、TCPスレッドはリッスンが中断されますが、UDPリスナーはリッスンされません。具体的には、TCPスレッドはServerSocket.accept()を使用します(実際には接続しないで返す)。 UDPスレッドはDatagramSocket.receive()を使用し、その方法は終了しません。DatagramSocket.receiveのスレッドを中断します

これは私のJRE、私のOSでの問題である、または私はちょうど(Datagram)Socket.close()に切り替える必要がありますか?

UPDATE:私は、問題のanalysisを見つけました。これは、動作が一貫していないことを確認します。

+0

他の人が同じ問題を扱うのを助けるために、私の 'ServerSocket.accept()'は接続せずに戻っていませんでした。私のブラウザ(FF4b10)がfaviconを3回要求するので、戻ってきました。リクエストの1つがThread.interrupted()チェックをトリッピングしていました。私は 'close()'を使って切り替えます。 – SEK

答えて

26

ネットワークIOを中断するための一般的なイディオムは、チャネルを閉じることです。あなたが効果的にそれを送信または受信を待っている間に中断する必要があるなら、それは良い賭けになるでしょう。

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

自分自身でより良い言葉にすることはできませんでした。ありがとう! – SEK

0

DatagramSocket.receiveブロックし、データグラムを受信します。あなたがする必要があるのは、おそらくsetSoTimeoutを使ってタイムアウトにすることです。

+0

この場合、タイムアウトは適切な解決策ではありません。また、 'DatagramSocket.receive()'は中断されなければなりません。なぜなら、これは変です。 – SEK

+1

@SEK:そうしてはいけません。 Javadocにはこういったものは何もありません。中断可能な動作が必要な場合は、InterruptibleChannelを実装するDatagramChannelを使用する必要があります。 – EJP

2

私が知る限り、ブロックされたソケットを中断するには、close()が適切です。部分的な読み込みや書き込みをすでに行っている可能性のあるものを中断して保持することは、不必要に複雑になります。 「成功」または「あきらめる」結果に対処するだけで済むのは簡単です。

関連する問題