使用readLine()接收数据时,即使我在消息的末尾添加了“\ n” 在发送消息时使用.flush,读取我的消息的while循环仍会阻塞。 只有在关闭套接字连接时,才会离开循环。
这是客户端代码:
bos = new BufferedOutputStream(socket.
getOutputStream());
bis = new BufferedInputStream(socket.
getInputStream());
osw = new OutputStreamWriter(bos, "UTF-8");
osw.write(REG_CMD + "\n");
osw.flush();
isr = new InputStreamReader(bis, "UTF-8");
BufferedReader br = new BufferedReader(isr);
String response = "";
String line;
while((line = br.readLine()) != null){
response += line;
}
和服务器的代码:
BufferedInputStream is;
BufferedOutputStream os;
is = new BufferedInputStream(connection.getInputStream());
os = new BufferedOutputStream(connection.getOutputStream());
isr = new InputStreamReader(is);
String query= "";
String line;
while((line = br.readLine()) != null){
query+= line;
}
String response = executeMyQuery(query);
osw = new OutputStreamWriter(os, "UTF-8");
osw.write(returnCode + "\n");
osw.flush();
我的代码在循环时阻塞服务器。 感谢。
答案 0 :(得分:13)
BufferedReader将继续读取输入,直到它到达结尾(文件末尾或流或源等)。在这种情况下,'end'是套接字的关闭。因此,只要Socket连接打开,您的循环就会运行,BufferedReader将等待更多输入,每次到达'\ n'时都会循环。
答案 1 :(得分:3)
这是因为while循环中的条件:while((line = br.readLine()) != null)
如果readLine返回null
,则每次迭代都会读取一行,并将循环调出。
readLine仅返回null,如果达到eof(= socked关闭),并且如果读取'\ n'则返回String。
如果你想在readLine上退出循环,你可以省略整个while循环而只是这样做:
line = br.readLine()
答案 2 :(得分:2)
我尝试了很多解决方案,但我找到的唯一一个没有阻止执行的解决方案是:
BufferedReader inStream = new BufferedReader(new
InputStreamReader(yourInputStream));
String line;
while(inStream.ready() && (line = inStream.readLine()) != null) {
System.out.println(line);
}
如果下一个inStream.ready()
调用将阻止执行,readLine()
将返回false。
答案 3 :(得分:1)
这是因为InputStream未准备好变为红色,因此它会阻塞in.readLine()。 请试试这个:
boolean exitCondition= false;
while(!exitCondition){
if(in.ready()){
if((line=in.readLine())!=null){
// do whatever you like with the line
}
}
}
当然你必须控制exitCondition。
另一个选项可以是使用nio包,它允许异步(不阻塞)读取,但这取决于你的需要。
答案 4 :(得分:1)
最好避免使用readline()
。此方法对于网络通信很危险,因为某些服务器不会返回LF/CR
符号,并且您的代码将被卡住。当您从文件中读取内容时,这并不重要,因为无论如何您都将到达文件末尾并且流将被关闭。
public String readResponse(InputStream inStreamFromServer, int timeout) throws Exception {
BufferedReader reader = new BufferedReader(new InputStreamReader(inStreamFromServer, Charsets.UTF_8));
char[] buffer = new char[8092];
boolean timeoutNotExceeded;
StringBuilder result = new StringBuilder();
final long startTime = System.nanoTime();
while ((timeoutNotExceeded = (TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime) < timeout))) {
if (reader.ready()) {
int charsRead = reader.read(buffer);
if (charsRead == -1) {
break;
}
result.append(buffer, 0, charsRead);
} else {
try {
Thread.sleep(timeout / 200);
} catch (InterruptedException ex) {
LOG.error("InterruptedException ex=", ex);
}
}
}
if (!timeoutNotExceeded) throw new SocketTimeoutException("Command timeout limit was exceeded: " + timeout);
return result.toString();
}
它有一个超时时间,如果花费很多时间,您可以中断通信
答案 5 :(得分:0)
如果你想在不被强制关闭的情况下获取套接字中的内容,只需使用ObjectInputStream和ObjectOutputStream ..
<强> 实施例 强>
ObjectInputStream ois;
ObjectOutputStream oos;
ois = new ObjectInputStream(connection.getInputStream());
String dataIn = ois.readUTF(); //or dataIn = (String)ois.readObject();
oos = new ObjectOutputStream(connection.getOutputStream());
oos.writeUtf("some message"); //or use oos.writeObject("some message");
oos.flush();
.....
答案 6 :(得分:0)
readline()和read()将被阻止。所以你应该关闭socket:
Socket.shutdownInput();//after reader
Socket.shutdownOutput();//after wirite
而不是Socket.close();