Java 套接字,BufferedReader挂起在readLine()上

Java 套接字,BufferedReader挂起在readLine()上,java,sockets,io,bufferedreader,Java,Sockets,Io,Bufferedreader,我有一台服务器,它最初执行以下操作:- 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()));
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”
  • “\n”
  • “将其传递给foo\n”
  • “\n”
问题是,有时“foo”没有得到响应。它挂在
readLine()

服务器中的
readLine()
使用预读来缓冲数据,而“foo”类被饿死的可能性有多大

如果我在客户端添加睡眠,它就会工作。但它始终有效的可能性有多大

  • “栏\n”
  • “你好吗?\n”
  • “\n”
  • 睡眠(1000)
  • “将其传递给foo\n”
  • “\n”

如何解决这个问题?感谢您在这方面提供的帮助。

第一个
BufferedReader
中已经有数据(已从套接字读取,并且不再从套接字可用),因此将第一个示例中创建的
BufferedReader
传递给读取应用程序特定消息的类,而不是从套接字创建一个新的
BufferedReader

eee的解决方案非常有效。我试图读取SMTP会话的输出,但它会在以下位置阻塞:

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

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

我什么都看得很清楚。br是一个BufferedReader对象,顺便说一句。

我也有同样的问题,下面是我的解决方案:

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 "";
}
试试看{
StringBuilder响应=新建StringBuilder();
response.append(“服务器->客户端消息:”).append(CRLF);
//无限循环
while(true){
//检查流是否准备就绪
if(in.ready()){
//实际阅读行
lastLineFromServer=in.readLine();
//如果我们在流的末尾有正常的行为
if(lastLineFromServer!=null){
响应
.append(lastLineFromServer)
.附加(CRLF);
}否则{
返回response.toString();
}
}else{//如果流未就绪
//如果未超过尝试次数
if(尝试次数<尝试次数的最大值){
numberOfTry++;
//等待流准备就绪
睡眠(在下一次尝试之前的最大延迟);
}else{//如果已超出尝试次数
//增加了警告,事情会变得很糟糕
响应
.append(“警告\r\n”)
.append(“服务器发送响应不正确。\r\n”)
.append(“响应可能不完整”)
.附加(CRLF);
返回response.toString();
}
}
}
}捕获(例外情况除外){
例如printStackTrace();
返回“”;
}

答案可能迟了,但这是2020年最简单和最新的答案,只需使用输入流
read()
方法从套接字服务器或客户端接收数据即可

当客户端断开连接或服务器关闭连接时,将抛出
EOFEException

private String waitForData() throws IOException {
    String data = "";
    do {
        int c = inputStream.read();
        if (c > -1) data += (char) c;
        else throw new EOFException();
    } while (inputStream.available() > 0);
    return data;
}

在尝试读取数据之前,您还可以使用BufferedReader的
ready()
检查数据是否准备就绪。在循环中执行此操作如何解决问题?
ready()-告诉此流是否准备好读取。通常,我将它与
read()
一起使用。我不会将它与
readLine()
一起使用,例如:
while(true){if(br.ready()){br.read(cb);cb.flip();String msg=cb.toString();if(msg==null)break;}}
cb是具有特定缓冲区大小的
CharBuffer
。此技术允许读取缓冲区中允许的行数。有关详细信息。。。我不能那样做。服务器不在我的控制之下。foo类在我的控制下。为什么BufferedReader应该提前阅读?我们不能控制吗?不应BufferedReader提前读取(通过询问),但不清空套接字。请注意,第一个“\n”确保服务器停止读取。它会停止读取,您不能更改它;这是它的读取方法的契约:,int,int)这是对我有效的解决方案。readLine()被无缘无故地卡住了,.ready()对我来说非常有效。在ready()之后使用readLine()时,通常要小心。Ready()告诉您有数据要读取,但并不意味着它是一整行。所以readLine()仍然可以阻止。在我的情况下,br.ready()在第一种情况下始终为false