What happens when client closes connection before server is done reading bytes from BufferedInputStream?

886 Views Asked by At

I am reading a file being uploaded over the web and it is being sent through http and we are receiving through a BufferedInputStream. Sometimes we get a timeout exception in the middle of reading from the stream. My working theory is that the connection is being closed from the client before we can process the whole file. The file is in the order of mb.

Does this theory make sense? Does the client need to keep the connection open in order for the server to completely read bytes from the input stream?

2

There are 2 best solutions below

0
Manifest Man On

No good news in that case, data lost will occur.

0
rzwitserloot On

Does this theory make sense? Does the client need to keep the connection open in order for the server to completely read bytes from the input stream?

No.

As long as the BufferedInputStream has bytes in the buffer, any calls to read() / read(byte[]) / read(byte[], int, int) will simply give you data from the buffer and will never even touch the underlying inputstream.

As long as you don't touch said inputstream, it cannot just start throwing exceptions out of the clear blue sky. You need to call something on the actual socket inputstream (be it read, close, flush, write - something), in order to get an exception thrown.

What could happen is a mixed mode operation: You call e.g:

var raw = socket.getInputStream();
var buffered = new BufferedInputStream(raw);
byte[] b = new byte[1000];
buffered.read(b); // actually reads 4000 bytes into buffer, giving 1000 of them.
// 3000 left in the buffer!
byte[] c = new byte[2000];
buffered.read(c); // works fine and never touches raw. Can't throw.
byte[] d = new byte[2000];
buffered.read(d); // 'mixed mode'

Here, in the 'mixed mode' situation, the first 1000 bytes are filled by the buffer, but then raw.available() is invoked (source: The actual source code of BufferedInputStream.java); if it returns a non-zero number, then more data is fetched from raw directly; if it is 0, read() just returns (read() is under no obligation to read ALL the requested bytes; it merely needs to [A] read at least 1, and [B] return how much it did read; usually you want readNBytes instead).

However, in.available() is allowed to throw. If it does, voila.

However, a normal TCP close would not cause TimeoutExceptions.

A much more likely scenario is the following: Your code is simply not processing the data fast enough. The sending entity at some point is just fed up with it all and refuses to continue to let you hog a file handle and just hangs up on you. If you're already using a buffer, perhaps there's some network equipment in between that is dog slow, or the server is configured with unrealistic expectations of how fast your network connections are.