16

ソケット接続を使用して作成されたBufferedReaderとPrintWriterにタイムアウトを設定するにはどうすればよいですか?サーバーまたはクライアントのいずれかがクラッシュするまで機能する、現在サーバー用に持っているコードは次のとおりです。

while(isReceiving){
    str = null;
    BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
    PrintWriter pw = new PrintWriter(socket.getOutputStream(), true);

    while ((str = br.readLine()) != null){
        System.out.println("Processing command " + str);
        pw.println(client.message(str));
    }
}

このコードの範囲外で、1000msのソケットタイムアウトを課しました。これは、最初の接続を待機するときに意図したとおりに機能します。しかし、プログラムは(str = br.readLine())でブロックします。クライアントがハングしたりクラッシュしたりした場合、プロセスを終了しない限り、ブロックが停止することはありません(それでも常に機能するとは限りません)。

問題のクライアントコードはこれに非常に似ており、同様の方法でブロックしています。

4

4 に答える 4

20
  1. ソケットに読み取りタイムアウトを設定する必要がありますSocket.setSoTimeout()。これにより、SocketTimeoutException指定された読み取りタイムアウトが期限切れになると、すべての読み取りメソッドがをスローします。NB読み取りタイムアウトは、ストリームではなく、基になるSocket,ビアに設定されますSocket.setSoTimeout().

  2. TCPには書き込みタイムアウトのようなものはありません。

于 2011-07-23T08:48:28.897 に答える
17

GoogleのGuavaライブラリのSimpleTimeLimiterを使用できます。

サンプルコード(Java 8):

BufferedReader br = ...;
TimeLimiter timeLimiter = new SimpleTimeLimiter();

try {
    String line = timeLimiter.callWithTimeout(br::readLine, 10, TimeUnit.SECONDS);
} catch (TimeoutException | UncheckedTimeoutException e) {
    // timed out
} catch (Exception e) {
    // something bad happened while reading the line
}
于 2015-07-24T13:20:43.180 に答える
5

この質問Timerの回答は、を使用して接続を閉じる興味深い方法を説明しています。これが読み取りの途中で機能するかどうかは100%わかりませんが、一見の価値があります。

その答えからコピー:

TimerTask ft = new TimerTask(){
   public void run(){
     if (!isFinished){
       socket.close();
     }
   }
};

(new Timer()).schedule(ft, timeout);

isFinishedストリームからの読み取りが完了したときに設定する必要があるboolean変数である必要があります。true

于 2011-07-22T16:16:01.457 に答える
2

socket.close()を呼び出しても、br.readLine()でブロックが中断されないようだったので、少し回避策を実行しました。クライアントをサーバーから切断するとき、私は単に文字列「bye」を送信し、このコマンドを受信したときにソケット接続を閉じるようにサーバーに指示しました。

while ((str = br.readLine()) != null){
    // If we receive a command of "bye" the RemoteControl is instructing
    // the RemoteReceiver to close the connection.
    if (str.equalsIgnoreCase("bye")){
        socket.close();
            break;
    }
    System.out.println("Processing command " + str);
    pw.println(client.message(str));
}
于 2011-07-22T19:31:42.607 に答える