InputStream throwing SocketTimeOutException on read when file is not available - java

Trying to read some image files from a server and using socket programming for the same.
But I am getting socketTimeOut exception when there is no file exist. Not only that loosing the connection to the server.
How can I avoid loosing the connection to the server when there is no file exist.
InputStream inputStream = new BufferedInputStream(socket().getInputStream());
int i = -1;
while ((i = bufferedInputStream.read()) != -1) {
byteArrayOutputStream.write(i);
}
In the above code I am getting exception, when I call read() on bufferedInputStream. How can I handle this exception and loosing connection to server.
Thanks

You don't get that exception 'when the file [doesn't] exist'. You get it when you have set a read timeout and no data has arrived within the timeout, if your timeout is too short, raise it. If you want to wait forever, remove it. It's your timeout, you set it.
If you get a SocketTimeoutException you don't lose the connection. What makes you think you did?

Related

java inputstream hangs when closing

I need to know what could cause the InputStream to hang indefinitely on close. Here's my code.
URL url = new URL("ftp://..");
InputSream is = url.openStream();
BufferedReader reader = new InputStreamReader(new GZIPInputStream(is));
try{
while(true){
if(reader.readline() == null){
break;
}
}
}catch(Exception e){
e.printStackTrace();
} finally{
System.out.println("Closing reader");
is.close(); // sometimes hangs indefinitely
System.out.println("Reader closed");
}
Closing InputStream or BufferedReader has the same effect.
I need to know what could cause the InputStream to hang indefinitely on close
I think it is the nature of the particular input stream that you are using.
You have a stream open to a read a file from an FTP server. Depending on the protocol driver that is being used on the Java client side, when you close() the file it may be attempting to close an active FTP session. This could involve exchanging network packets with the remote server, and if there is a network problem or the server has died, then that could take "a long time" ... depending on how long network timeouts have been set to, etc.
It could also be something like this:
Java HttpURLConnection InputStream.close() hangs (or works too long?)
My recommendation you be to capture a thread stacktrace while a connection is hung in close() and then delve into the Java codebase to figure out where exactly it is hung. (There are too many possible places for a problem to occur to investigate this without concrete evidence.)
Also try removing the GZIPInputStream from the stack to see if that makes any difference.
Finally, if you come back to us with more evidence, please tell us the precise Java version you are using and the real URL of the FTP server.

How to read the data from datastream

Please help me out on how to read the stream of data in java. My requirement is to make the telnet connection to the router. This part is accomplished. From the router, Have to connect to the xxx remote machine using its ip address and port number through telnet. While making this connection, i am getting some response. But while reading, the program control stops at read() method of InputStream class. Here are the code snippet which i am using to read the stream of data.
buff = new byte[4*1024];
ret_read = 0;
do
{
ret_read = in.read(buff); // Program control gets hanged here. Once all the data are read...
if(ret_read > 0)
{
System.out.println(new String(buff,0,ret_read));
}
}while(ret_read > 0);
What is happening is the read is blocking and waiting for more data to be sent on the stream, it will continue to do that until the stream is closed or more data is sent.
You need to either use a non-blocking read, put a timeout on the read, or close the stream server side after it finishes sending the data.

How to detect FIN - tcp flag in java application?

I have long-lasting TCP connection between two computers (second not under my control). Second computer can send FIN flag at every moment, and first must close connection corrent (send FIN flag back to second computer).
How can I know that the second computer sending a FIN flag and when I must cause socket.close() method of my Java application?
Normally, you have to read the connection and when this returns -1 for EOF or an appropriate IOException, you can close the connection. Note: SocketTimeoutException doesn't mean the connection is closed.
an example.
boolean ok = false;
try {
int b = in.read();
ok = b >= 0;
if (!ok)
throw new EOFException();
} finally {
if (!ok)
in.close();
}
Detecting a soft connection close by the other side (when they manage to send FIN/RST flags) is only partially possible with the old Java I/O library. You will learn of a broken connection only via a timeout, so it may be far from immediate. Your threads may hang for a long time before they realize that the party at the other end is long gone.
In order to handle it better, you need to use nio. There, such a situation will be recognized by the Selector saying there is data ready for reading but then read on the channel returning less than zero. This will allow you to learn about soft connection resets almost immediately.
On the other hand, a hard connection termination (e.g. someone cutting the wire or network being down) can only be detected via timeouts regardless of which libraries you use as it's a property of the TCP protocol itself.
As explained above, the Socket's properties (isClosed, isConnected, etc) are not helpful. A proper solution would be to set a reasonable SO_TIMEOUT and read from the socket:
In case of connection closed by the peer, the read operation would return with '-1'
In case of read timeout, the read operation would throw SocketTimeoutException.
(Scala code)
val socket = new Socket("localhost", 8888)
socket.setSoTimeout(10000) /* Set reasonable read timeout */
try {
val res = socket.getInputStream().read()
if (res < 0)
... /* Socket closed */
else
... /* Socket read succeeded */
} catch {
case _: SocketTimeoutException => ... /* Socket not closed */
case _ => ... /* Merde */
}

Connection reset while streaming xml

My code needs to download a big xml file (500MB) inside a GZIPInputStream and process it doing some operations for every object. Those operations take time to be completed, and I have many objects to process. I'm using commons http-client 3.1 and stax.
public void download(String url) throws HttpException, IOException,
XMLStreamException, FactoryConfigurationError {
GetMethod getMethod = new GetMethod(url);
try {
httpClient.executeMethod(getMethod);
Header contentEncoding = getMethod.getResponseHeader("Content-Encoding");
if (contentEncoding != null) {
String acceptEncodingValue = contentEncoding.getValue();
if (acceptEncodingValue.indexOf("gzip") != -1) {
processStream(new GZIPInputStream(getMethod.getResponseBodyAsStream()));
return;
}
}
processStream(getMethod.getResponseBodyAsStream());
return;
} finally {
getMethod.releaseConnection();
}
}
protected void processStream(InputStream inputStream) throws XMLStreamException, FactoryConfigurationError {
XMLStreamReader xmlStreamReader = XMLInputFactory.newFactory().createXMLStreamReader(inputStream);
//parses xml with Stax
//executes some long operations for each object
}
When I run the code it works till, after two or three hours, I get a SocketException: Connection reset.
Looks like the server has closed the connection, is it correct? Is there a way to avoid this error without any change on server-side? If not, how can I deal with it to avoid re-running my application from the beginning?
com.ctc.wstx.exc.WstxIOException: Connection reset
at com.ctc.wstx.sr.StreamScanner.throwFromIOE(StreamScanner.java:708)
at com.ctc.wstx.sr.BasicStreamReader.next(BasicStreamReader.java:1086)
.................
Caused by: java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(SocketInputStream.java:168)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:218)
at java.io.BufferedInputStream.read1(BufferedInputStream.java:258)
at java.io.BufferedInputStream.read(BufferedInputStream.java:317)
at org.apache.commons.httpclient.ChunkedInputStream.read(ChunkedInputStream.java:182)
at java.io.FilterInputStream.read(FilterInputStream.java:116)
at org.apache.commons.httpclient.AutoCloseInputStream.read(AutoCloseInputStream.java:108)
at java.util.zip.InflaterInputStream.fill(InflaterInputStream.java:221)
at java.util.zip.InflaterInputStream.read(InflaterInputStream.java:141)
at java.util.zip.GZIPInputStream.read(GZIPInputStream.java:92)
at java.io.FilterInputStream.read(FilterInputStream.java:90)
at com.ctc.wstx.io.UTF8Reader.loadMore(UTF8Reader.java:365)
at com.ctc.wstx.io.UTF8Reader.read(UTF8Reader.java:110)
at com.ctc.wstx.io.ReaderSource.readInto(ReaderSource.java:84)
at com.ctc.wstx.io.BranchingReaderSource.readInto(BranchingReaderSource.java:57)
at com.ctc.wstx.sr.StreamScanner.loadMore(StreamScanner.java:992)
at com.ctc.wstx.sr.StreamScanner.loadMore(StreamScanner.java:1034)
at com.ctc.wstx.sr.StreamScanner.getNextChar(StreamScanner.java:794)
at com.ctc.wstx.sr.BasicStreamReader.parseNormalizedAttrValue(BasicStreamReader.java:1900)
at com.ctc.wstx.sr.BasicStreamReader.handleNsAttrs(BasicStreamReader.java:3037)
at com.ctc.wstx.sr.BasicStreamReader.handleStartElem(BasicStreamReader.java:2936)
at com.ctc.wstx.sr.BasicStreamReader.nextFromTree(BasicStreamReader.java:2848)
at com.ctc.wstx.sr.BasicStreamReader.next(BasicStreamReader.java:1019)
One suggestion would be to cache the file locally and then process it later.
ie. your handler simply reads the stream and writes it to a temp file on disk. Then it closes the stream and processes the data from the temp file.
This is probably a good approach anyway as, even if you can keep the link up, the possibilities of some network outage, reduced QoS and so on may make retrieving the file unreliable. You might also be preventing the server from updating it for the entire duration of your processing, which is a bit anti-social.
If you cannot copy the xml to you local computer try to see if the connection timed out. Maybe the processing of the xml takes too long and the connection gets reset by one of the intermediate servers

How to timeout a read on Java Socket?

I'm trying to read items from a socket and I notice that if there is nothing on the stream of the socket it will stay at the read and back up my application. I wanted to know if there was a way to set a read timeout or terminate the connection after a certain amount of time of nothing in the socket.
If you write Java, learning to navigate the API documentation is helpful. In the case of a socket read, you can set the timeout option, e.g.:
socket.setSoTimeout(500);
This will cause the InputStream associated with the socket to throw a SocketTimeoutException after a read() call blocks for one-half second. It's important to note that SocketTimeoutException is unique among exceptions thrown by such read() calls, because the socket is still valid; you can continue to use it. The exception is only a mechanism to escape from the read and decide if it's time to do something different.
while (true) {
int n;
try {
n = input.read(buffer);
catch (SocketTimeoutException ex) {
/* Test if this action has been cancelled */
if (Thread.interrupted()) throw new InterruptedIOException();
}
/* Handle input... */
}
If this socket was created through a URLConnection to perform a web request, you can set the read and connect timeouts directly on the URLConnection before reading the stream:
InputStream createInputStreamForUriString(String uriString) throws IOException, URISyntaxException {
URLConnection in = new URL(uriString).openConnection();
in.setConnectTimeout(5000);
in.setReadTimeout(5000);
in.setAllowUserInteraction(false);
in.setDoInput(true);
in.setDoOutput(false);
return in.getInputStream();
}
Yes, there should be an override of Read() that accepts a timeout value. By 'override' I am not suggesting anyone write one, I am pointing out that one of the overrides of the socket methods he is using takes a timeout value.

Categories

Resources