vg said:
John C. Bollinger said:
vg wrote:
I'm reading data from a socket (an HTTP request) using a
BufferedReader. The read(char[], int, int) method blocks even though
data is available (i'm testing locally).
Testing locally does not necessarilly mean that data is always available
without blocking. How do you know that the method blocks, or
alternatively, how do you know that data is available?
When I run my app normally, it hungs immediately after submiting data
to the server. Debuging revealed that the read() method was the source
of blocking. I admit I cannot be 100% sure that the data is really
available but I was testing with less than 10kB of data sent from a
locally opened browser to my locally runing server.
My question is why it blocks
since the javadocs say this method should never block! Or I'm missing
something here?
Well, you're at least adding something to what is actually in the docs,
which do _not_ say that the method never blocks. The docs appear to say
that it will not block if there is at least one character available or
at the end of the stream, but that otherwise it will.
Please, Sir, read the javadoc from the BufferedReader.read() method! I
quote:
<<This iterated read continues until one of the following conditions
becomes true:
· The specified number of characters have been read,
· The read method of the underlying stream returns -1, indicating
end-of-file, or
· The ready method of the underlying stream returns false, indicating
that further input requests would block. >>
Therefore, this method always (should) abort the reading when the
stream is drained! They say it checks the ready() method of the
underlying stream...
This is my code, where len initally holds the total number of bytes I
have to read:
pos = 0;
char b[] = new char[len];
while (len > 0) {
if ((dim = reader.read(b, pos, len)) != -1) {
len -= dim;
pos += dim;
}
}
Two things:
Firstly, BufferedReader calls Reader.read(char[], int, int) which can
block. I read the docs to say that once the first read has returned, it
will attempt to keep reading any additional available characters, so
long as the conditions above are true.
Also, your loop termination clause may be flawed:
If the read returns -1 (i.e. end of stream), you will end up in a
spinloop trying to read from a closed stream, and getting -1 every time,
never decrementing len, and never exiting the while loop.
I suggest that you terminate the while loop if dim == -1, and check to
see if (len>0) when you have exited the while.
e.g.:
pos=0;
char b[] = new char[len];
int dim = 0;
while ((dim = reader.read(b, pos, b.length - pos)) > -1) {
pos += dim;
}
if (pos < b.length) {
System.err.println("Failed to read all the data, got " + pos +
" of " + b.length + " characters");
}
Note the side effect that len is not changed to be "0" at the end of
this loop, which may be relevant in your code.
Regards,
Rogan