Note that there are some explanatory texts on larger screens.

plurals
  1. POIs Socket.getInputStream().read(byte[]) guaranteed to not block after at least some data is read?
    primarykey
    data
    text
    <p>The JavaDoc for the class InputStream says the following:</p> <blockquote> <p>Reads up to len bytes of data from the input stream into an array of bytes. An attempt is made to read as many as len bytes, but a smaller number may be read. The number of bytes actually read is returned as an integer. This method blocks until input data is available, end of file is detected, or an exception is thrown.</p> </blockquote> <p>This corresponds to my experience as well. See for instance the example code below:</p> <pre><code>Client: Socket socket = new Socket("localhost", PORT); OutputStream out = socket.getOutputStream(); byte[] b = { 0, 0 }; Thread.sleep(5000); out.write(b); Thread.sleep(5000); out.write(b); Server: ServerSocket server = new ServerSocket(PORT); Socket socket = server.accept(); InputStream in = socket.getInputStream(); byte[] buffer = new byte[4]; System.out.println(in.read(buffer)); System.out.println(in.read(buffer)); Output: 2 // Two bytes read five seconds after Client is started. 2 // Two bytes read ten seconds after Client is started. </code></pre> <p>The first call to read(buffer) blocks until input data is available. However the method returns after two bytes are read, even though there is still room in the byte buffer, which corresponds with the JavaDoc stating that 'An attempt is made to read as many as len bytes, <em>but a smaller number may be read</em>'. However, is it guaranteed that the method will not block once at least one byte of data is read when the input stream comes from a socket?</p> <p>The reason I ask is that I saw the following code in the small Java web server <a href="http://elonen.iki.fi/code/nanohttpd/" rel="nofollow">NanoHTTPD</a>, and I wondered if a HTTP Request smaller than 8k bytes (which most requests are) potientially could make the thread block indefinately unless there is a guarantee that it won't block once some data is read.</p> <pre><code>InputStream is = mySocket.getInputStream(); // Read the first 8192 bytes. The full header should fit in here. byte[] buf = new byte[8192]; int rlen = is.read(buf, 0, bufsize); </code></pre> <hr> <p><strong>Edit</strong>:</p> <p>Let me try to illustrate once more with a relatively similar code example. EJP says that <em>the method blocks until either EOS is signalled or at least one byte of data has arrived, in which case it reads however many bytes of data have arrived, without blocking again, and returns that number</em>, which corresponds to the <a href="http://docs.oracle.com/javase/7/docs/api/java/io/InputStream.html#read%28byte%5B%5D,%20int,%20int%29" rel="nofollow">JavaDoc</a> for method read(byte[], int, int) in the class InputStream. However, if one actually looks at the source code it is clear that the method indeed blocks until the buffer is full. I've tested it by using the same Client as above and copying the InputStream-code to a static method in my server example.</p> <pre><code>public static void main(String[] args) throws Exception { ServerSocket server = new ServerSocket(PORT); Socket socket = server.accept(); InputStream in = socket.getInputStream(); byte[] buffer = new byte[4]; System.out.println(read(in, buffer, 0, buffer.length)); } public static int read(InputStream in, byte b[], int off, int len) throws IOException { if (b == null) { throw new NullPointerException(); } else if (off &lt; 0 || len &lt; 0 || len &gt; b.length - off) { throw new IndexOutOfBoundsException(); } else if (len == 0) { return 0; } int c = in.read(); if (c == -1) { return -1; } b[off] = (byte)c; int i = 1; try { for (; i &lt; len; i++) { c = in.read(); if (c == -1) { break; } b[off + i] = (byte)c; } } catch (IOException ee) { } return i; } </code></pre> <p>This code will have as its output:</p> <pre><code>4 // Four bytes read ten seconds after Client is started. </code></pre> <p>Now clearly there is data available after 5 seconds, however the method still blocks trying to fill the entire buffer. This doesn't seem to be the case with the input stream that Socket.getInputStream() returns, but is it <strong>guaranteed</strong> that it will never block once data is available, like the JavaDoc says but not like the source code shows?</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload