2017-02-05 17 views
1

ここでは、2秒ごとにサーバーの応答を確認するスレッドを作成していますが、client.monitorResponse()readLine()メソッドであり、応答が受信されるまで続行されません。 。私は、サーバーに接続されたクライアントソケットを経由して応答を拾っていますソケットストリームでBufferedReaderのタイムアウトを設定する方法

public SocketObject(Socket client, int numberOfClients) throws Exception { 
    socket = client; // the .accept() socket is passed through 
    // this is because I assign them ID's for later use (I hold an ArrayList of sockets) 
    this.clientId = numberOfClients; 

    // both these are static to the class 

    outputStream = new PrintWriter(client.getOutputStream()); 
    inputStream = new BufferedReader(new InputStreamReader(client.getInputStream())); 
} 

public void sendResponse(String response) { 
    outputStream.println(response); 
} 

client = new ClientObject("localhost"); 
timer.scheduleAtFixedRate(new TimerTask() { 
    @Override 
    public void run() { 
     try { 
      String response = null; 
      if(!(response = client.monitorResponse()).isEmpty()) { 
       System.out.println("Response: " + response); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
    } 
}, 2000, 2000); 

私は(clientが確立ソケットがある)ので、などのサーバーを経由して応答を送信しています:

public ClientObject(String hostname) throws IOException { 

    // socket is static to this class 

    socket = new Socket(hostname, 4444); 
    System.out.println("Connected to " + hostname + " on port 4444..."); 

    // both static to this class 

    outputStream = new PrintWriter(socket.getOutputStream(), true); 
    inputStream = new BufferedReader(new InputStreamReader(socket.getInputStream())); 

    System.out.println("Successfully started a stream on " + hostname); 
    this.hostname = hostname; 
} 

public String monitorResponse() throws Exception { 
    System.out.println("Listening for a response..."); 
    return inputStream.readLine(); 
} 

デバッグコンソールにのみメートルを語っされたらが応答を聞く...出力を表示しますそれはスレッド内でinputStream.readLine()メソッドを通過しないということです。とにかくBufferedReaderにタイムアウトを追加できますか?私はBufferedReaderを作成する前にソケットに.setSoTimeout()を追加するような複数のソリューションを試しましたが、指定された時間後に接続/ソケットを閉じることができました。

ご協力いただければ幸いです。

+0

なぜですか?サーバーが応答を送信している場合は、それを読み取る必要があります。タイムアウトを実装すると、次回に応答が読み込まれ、コードが混乱することになります。レスポンスはオプションですか?この場合、アプリケーションプロトコルを誤って設計してしまいました。また、このコードを 'Timer'で実行している場合は、タイムアウトは必要ありません。タイマータスクには他に何もしないでブロックします。実際には、タイマを必要とせず、読み込みループを持つスレッドだけでも必要です。あなたはベルトとブレースをここに着ています。 – EJP

+0

ええ、私はそれが要求を読むことができなかったことを認識しました:それは問題を引き起こしていたものです。 'PrintWriter()'の2番目のパラメータが欠落していました。これは、Socket上で 'getOutputStream()'を使用していたサーバでtrueに設定する必要がありました。 @EJP – KDOT

答えて

0

ノンブロッキング(NIO)リクエストを使用し、その間に改行を探すチャンクを読み込む必要があります。通常Javaでは、使用しているStreamクラスのNIOバージョンを探し、それを使ってN秒ごとに新しいコンテンツをチェックするだけです。

String partialLine=""; 
public static String monitorResponse() throws Exception { 
    System.out.println("Listening for a response..."); 
    int nextByte; 
    String nextChar; 
    while (inputStream.ready()) { 
     nextByte = inputStream.read(); 
     nextChar = Character.toString ((char) nextByte); 
     partialLine += nextChar; 
     if ("\n".equals(nextChar)) { 
      String line = partialLine; 
      partialLine = ""; 
      return line.replace("\r\n", ""); 
     } 
    } 
    return ""; 
} 

の詳細はhttp://tutorials.jenkov.com/java-nio/nio-vs-io.htmlをチェックアウト:最小限の変更であなたのケースでは、ブロッキングを防止するためにBufferedReader.ready()で通話を遮断するあまり派手で効率的な方法を使用することができます。

+0

ここにタイムアウトを実装するものはありません。 'readLine()'とは異なり、 '\ r \ n'も正しく処理しません。 – EJP

+0

今削除されたコメントは、 'readLine()'とは異なり、 '\ r \ n'がデータ内で' \ r'を返すように正しく処理されません。 'readLine()'は、行終了のすべての可能な場合を処理します。あなたのコードはそうではありません。私の答えは接続を閉じないし、読み取りタイムアウトを設定することはまさに彼が求めているものです。 – EJP

+0

テストされ、更新されました。 'BufferedReader.readLine()'のようにEOLが削除されているのではなく、コンパイルする前に修正するいくつかの構文エラーと、 'return null'の代わりに' return "' 'が必要です。 2秒ごとに行を読みます。フルラインがまだ利用できない場合は、2秒後にもう一度試行します。 2つ以上の回線が利用可能な場合は、2つの回線の間に到着順にそれらの回線を読み取ります。それが冗長であったため、私はif条件を削除しました。 – NotGaeL

0

私はBufferedReaderにタイムアウトを追加できますか?

いいえ、ただし、Socketには、Socket.setSoTimeout()でタイムアウトを設定できます。

私はBufferedReaderを作成する前にソケットに.setSoTimeout()を追加するなど、複数の解決策を試しましたが、指定した時間後に接続/ソケットを閉じることができました。

いいえソケットを閉じません。それはSocketTimeoutExceptionを投げ、あなたはそれを捕らえて適切に扱うべきです。ソケットが閉じている場合は、閉じています。解決策:しないでください。

+0

私はそれを理解しました。 'new InputStreamReader(socket.getInputStream())'に2番目のブール値のパラメータがありませんでした。これは 'true'に設定する必要があります。 – KDOT

+0

'new InputStreamReader()'にはブール値の第2引数はありません。 – EJP

+0

私は 'new PrintWriter()'を意味しました。申し訳ありませんが、良いメッセージ^ – KDOT

関連する問題