BufferedReader readLine() blocks

前端 未结 7 2038
轻奢々
轻奢々 2020-12-06 02:02

When receiving data using readLine(), even though I put a \"\\n\" at the end of the message using the .flush when sending the message, the while loop that reads my message s

相关标签:
7条回答
  • 2020-12-06 02:39

    It'd be better avoid using readline(). This method is dangerous for network communications because some servers don't return LF/CR symbols and your code will be stuck. When you read from a file it isn't critical because you will reach end of the file anyway and stream will be closed.

    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();
    }
    

    It has a timeout and you can interrupt communication if it take a lot of time

    0 讨论(0)
  • 2020-12-06 02:40

    I tried a lot of solutions but the only one I found which wasn't blocking execution was:

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

    The inStream.ready() returns false if the next readLine() call will block the execution.

    0 讨论(0)
  • 2020-12-06 02:41

    readline() and read() will be blocked while socket doesn't close. So you should close socket:

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

    rather than Socket.close();

    0 讨论(0)
  • 2020-12-06 02:43

    The BufferedReader will keep on reading the input until it reaches the end (end of file or stream or source etc). In this case, the 'end' is the closing of the socket. So as long as the Socket connection is open, your loop will run, and the BufferedReader will just wait for more input, looping each time a '\n' is reached.

    0 讨论(0)
  • 2020-12-06 02:49

    if you want to get what's in the socket without being forced to close it simply use ObjectInputStream and ObjectOutputStream ..

    Example:

    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();
    
    .....
    
    0 讨论(0)
  • 2020-12-06 02:54

    This is because of the condition in the while-loop: while((line = br.readLine()) != null)

    you read a line on every iteration and leve the loop if readLine returns null.

    readLine returns only null, if eof is reached (= socked is closed) and returns a String if a '\n' is read.

    if you want to exit the loop on readLine, you can omit the whole while-loop und just do:

    line = br.readLine()

    0 讨论(0)
提交回复
热议问题