13

使用 readLine() 接收数据时,即使我在发送消息时使用 .flush 在消息末尾放置了一个“\n”,读取我的消息的 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();

我的代码在服务器 while 循环中阻塞。谢谢。

4

7 回答 7

20

BufferedReader 将继续读取输入,直到它到达末尾(文件或流或源等的结尾)。在这种情况下,“结束”是套接字的关闭。因此,只要 Socket 连接打开,您的循环就会运行,而 BufferedReader 只会等待更多输入,每次到达 '\n' 时都会循环。

于 2013-03-20T10:49:40.200 回答
11

我尝试了很多解决方案,但唯一没有阻止执行的解决方案如下:

BufferedReader inStream = new BufferedReader(new InputStreamReader(yourInputStream));
String line;
while(inStream.ready() && (line = inStream.readLine()) != null) {
    System.out.println(line);
}

如果下一次调用将阻止执行,inStream.ready()则返回 false 。readLine()

于 2017-09-25T16:42:29.557 回答
3

这是因为 while 循环中的条件:while((line = br.readLine()) != null)

您在每次迭代时读取一行,如果 readLine 返回则退出循环null

如果达到 eof(= socked 已关闭),readLine 仅返回 null,如果读取了 '\n',则返回 String。

如果你想在 readLine 上退出循环,你可以省略整个 while 循环,只做:

line = br.readLine()

于 2013-03-20T10:49:42.100 回答
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 包,它允许异步(非阻塞)读取,但这取决于您的需要。

于 2016-12-02T23:02:57.147 回答
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();
}

它有超时,如果需要很长时间,您可以中断通信

于 2020-04-12T19:57:48.003 回答
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();

.....
于 2015-01-18T18:02:31.260 回答
0

当套接字不关闭时,readline() 和 read() 将被阻塞。所以你应该关闭套接字:

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

而不是 Socket.close();

于 2018-04-03T07:25:52.423 回答