web-dev-qa-db-ja.com

ソケット、BufferedReaderがreadLine()でハングする

私は最初にこれを行うサーバーを持っています:-

_BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
for (;;) {
  String cmdLine = br.readLine();
  if (cmdLine == null || cmdLine.length() == 0)
     break; 
  ...
}
_

後で、ソケットを別のクラス「foo」に渡します。このクラスは、アプリケーション固有のメッセージを待ちます。

_ BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
 appCmd=br.readLine();
_

私のクライアントはこのシーケンスを送信します:

  • "納屋"
  • 「お元気ですか?\ n」
  • "\ n"
  • 「それをfooに渡す\ n」
  • "\ n"

問題は、「foo」が応答を受け取らないことがあるということです。 readLine()でハングします。

サーバーのreadLine()が先読みを使用してデータをバッファリングし、「foo」クラスが不足している可能性はどのくらいありますか?

クライアント側でスリープを追加すると、機能します。しかし、それが常に機能する可能性は何ですか?

  • "納屋"
  • 「お元気ですか?\ n」
  • "\ n"
  • sleep(1000);
  • 「それをfooに渡す\ n」
  • "\ n"

問題を解決する方法は?この点に関する助けに感謝します。

15
ashim

eeeのソリューションは完全に機能します。 SMTP会話からの出力を読み取ろうとしましたが、ブロックされます。

while ((response = br.readLine()) != null) {
    ...Do Stuff
}

変更先:

while (br.ready()) {
    response = br.readLine();
    ...Do Stuff
}

私はすべてをうまく読むことができます。 brはBufferedReaderオブジェクトです。

22
mojado

最初のBufferedReaderにはすでにデータがあり(ソケットから読み取られ、ソケットからは使用できなくなります)、最初の例で作成したBufferedReaderを次のクラスに渡します。ソケットから新しいBufferedReaderを作成するのではなく、アプリ固有のメッセージを読み取ります。

2
MeBigFatGuy

私は同じ問題を抱えていました、そしてここに私の解決策があります:

try {
    StringBuilder response = new StringBuilder();
    response.append("SERVER -> CLIENT message:").append(CRLF);
    //Infinite loop
    while (true) {
        //Checks wheather the stream is ready
        if (in.ready()) {
            //Actually read line 
            lastLineFromServer = in.readLine();
            //If we have normal behavior at the end of stream
            if (lastLineFromServer != null) {
                response
                        .append(lastLineFromServer)
                        .append(CRLF);
            } else {
                return response.toString();
            }
        } else {//If stream is not ready
            //If number of tries is not exceeded
            if (numberOfTry < MAX_NUMBER_OF_TRIES) {
                numberOfTry++;
                //Wait for stream to become ready
                Thread.sleep(MAX_DELAY_BEFORE_NEXT_TRY);
            } else {//If number of tries is exeeded
                //Adds warning that things go weired
                response
                        .append("WARNING \r\n")
                        .append("Server sends responses not poroperly.\r\n")
                        .append("Response might be incomplete.")
                        .append(CRLF);
                return response.toString();
            }
        }
    }
} catch (Exception ex) {
    ex.printStackTrace();
    return "";
}
1
Andrew Archer