BufferedReader readLine()块

时间:2013-03-20 10:46:46

标签: java sockets bufferedreader

使用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();

我的代码在循环时阻塞服务器。 感谢。

7 个答案:

答案 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)

当socket未关闭时,

readline()和read()将被阻止。所以你应该关闭socket:

Socket.shutdownInput();//after reader
Socket.shutdownOutput();//after wirite

而不是Socket.close();