套接字,BufferedReader 在 readLine() 处挂起
Posted
技术标签:
【中文标题】套接字,BufferedReader 在 readLine() 处挂起【英文标题】:Socket, BufferedReader hangs at readLine() 【发布时间】:2011-08-24 16:24:15 【问题描述】:我有一台服务器,它最初是这样做的:-
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”sleep(1000);
“将其传递给 foo\n”
“\n”
如何解决问题?感谢您在这方面的任何帮助。
【问题讨论】:
您还可以在尝试读取数据之前使用 BufferedReader 的ready()
来检查数据是否准备就绪。在循环中执行此操作
如何解决问题?
ready() - tell whether this stream is ready to be read
。通常,我将它与read()
一起使用。我不将它与readLine()
一起使用,例如:while(true) if (br.ready()) br.read(cb); cb.flip(); String msg = cb.toString(); if (msg == null) break;
cb 是具有一定缓冲区大小的CharBuffer
。这种技术将允许读取缓冲区中允许的行数。
更多...***.com/questions/5244839/…
【参考方案1】:
答案可能晚了,但这是2020年最简单最新的答案,只需使用输入流read()
方法从套接字服务器或客户端接收数据的简单方法即可。
EOFException
会在客户端断开或服务器关闭连接时抛出。
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;
【讨论】:
但是 inputStream.available() 有时会返回 0 并且当发送者发送消息并挂起 read() 消息时......【参考方案2】:我遇到了同样的问题,这是我的解决方案:
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 "";
【讨论】:
【参考方案3】:eee 的解决方案完美运行。我试图从 SMTP 对话中读取输出,但它会阻塞:
while ((response = br.readLine()) != null)
...Do Stuff
改为:
while (br.ready())
response = br.readLine();
...Do Stuff
我可以很好地阅读所有内容。 br 是一个 BufferedReader 对象,顺便说一句。
【讨论】:
这是对我有用的解决方案。 readLine() 无缘无故卡住了,而 .ready() 完美地为我工作 在 ready() 之后使用 readLine() 时通常要小心。 Ready() 告诉你有数据要读取,但不代表就是一整行。所以 readLine() 仍然可以阻塞。 在我的情况下 br.ready() 在第一种情况下总是错误的【参考方案4】:第一个 BufferedReader
中已经有数据(已从套接字读取,并且不再可从套接字获得),因此将第一个示例中创建的 BufferedReader
传递给读取应用程序的类特定消息,而不是从套接字创建一个新的BufferedReader
。
【讨论】:
我做不到。服务器不在我的控制之下。 foo 类在我的控制之下。为什么 BufferedReader 应该提前读取?我们不能控制吗? BufferedReader 不应该提前读取(通过查询)但不清空套接字。请注意,第一个“\n”确保服务器无法读取。 确实如此,但您无法更改;这就是它的 read 方法的约定:docs.oracle.com/javase/1.5.0/docs/api/java/io/…, int, int)以上是关于套接字,BufferedReader 在 readLine() 处挂起的主要内容,如果未能解决你的问题,请参考以下文章
关闭 BufferedReader/PrintWriter 是不是会关闭套接字连接?
为啥 BufferedReader read() 比 readLine() 慢得多?