0

I used a socket in my client class and try to get a string from server that is written into DataOutputStream successfully. Below is the sample code.

try(Socket socket = new Socket(ip, port);)
    {
        // Output and Input Stream
        DataInputStream input = new DataInputStream(socket.getInputStream());
        
        DataOutputStream output = new DataOutputStream(socket.getOutputStream());       
        
        //receive message from server
        while(true && input.available() > 0)
        {
            String message = input.readUTF();
            System.out.println(message);
            TextArea.setText(message);
        }
        
    } 
    catch (UnknownHostException e)
    {
        e.printStackTrace();
    }
    catch (IOException e) 
    {
        e.printStackTrace();
    }

However, when my client wants to show that message in a TextArea. It appears that input.available()=0 so it doesn't show that message. But when I print out the message string, it's really confusing that it is the exact string I want. Finally I just get rid of the while-statement and directly use TextArea.setText(message) to show that message. Anyone can help me clarify that?

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
helen
  • 61
  • 1
  • 9
  • Please read the documentation of [`available()`](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/io/InputStream.html#available()) carefully. You're making assumptions about its return value that are not correct. It doesn't tell you how much data can be read, it just tells you (an estimate of) how much data you can read without blocking. Related, possibly duplicate: [What does InputStream.available() do in Java?](https://stackoverflow.com/questions/3695372/what-does-inputstream-available-do-in-java) – Mark Rotteveel Apr 10 '21 at 08:15
  • You will need to create a proper protocol for your application, so that you know a message is available, and how long it is (although technically, `DataInputStream.readUTF()` will already do that last thing for you, because it reads a length-prefixed message). – Mark Rotteveel Apr 10 '21 at 08:21
  • @MarkRotteveel Thanks for that! I did look up the question your link shared. But I'm still confused by the concept of blocking... So for InputStream, the 'read()' always blocks other calls that require the data; therefore, 'input.available()' always return 0. Is that correct? – helen Apr 11 '21 at 13:12
  • An input stream implementation is allowed to return `0` if 1) it doesn't buffer data, and thus each read would block, or 2) it is hard or very expensive to detect if it has data available (e.g. because that can only be found somewhere deep in the bowels of native code). Especially in socket communications, blocking is extremely likely (e.g. because the other side hasn't sent anything yet, or it is still in transit, or because it has arrived at the socket, but given nothing has been read yet, no buffers in Java are filled yet, etc. – Mark Rotteveel Apr 11 '21 at 13:18
  • In short, `input.available()` is generally not useful to check or rely on. It has only value in some edge cases for performance optimization, where you know that the data is fully buffered, or where you might be able to handle buffered data now, and otherwise handle it at a later time (with a blocking read). – Mark Rotteveel Apr 11 '21 at 13:21
  • Very appreciate it!!! @MarkRotteveel – helen Apr 11 '21 at 13:37

1 Answers1

-1

What protocol is the server expecting? If the server is expecting some request first (e.g. HTTP), you'll need to send a request before expecting any bytes sent in the input stream (a reason that input.available is 0).

See here for an example: https://www.infoworld.com/article/2853780/socket-programming-for-scalable-systems.html

Curtis
  • 548
  • 3
  • 13
  • I'm using TCP. Does that also need to send a request? Also, I found a question which says the doc says input.available() always return 0. https://stackoverflow.com/q/3695372/12107043 which is confusing for me – helen Apr 10 '21 at 04:49