1

I am using the following code to download a file using Java but i want to detect when connection is lost. I ran the following code and while in the middle of downloading i disconnected my internet purposefully but no exception was thrown and it hanged. Even after turning on the connection back nothing happened. So, it hanged forever without any exceptions. Is there a way to make it throw an exception when the connection is lost? Thanks for the help!

package toplower.top;

import java.io.FileOutputStream;
import java.net.URL;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.util.*;

import javax.mail.*;

    public class testing {
        public static void main(String[] args) {

            try{

                URL website = new URL("http://b128.ve.vc/b/data/128/1735/asd.mp3");
                ReadableByteChannel rbc = Channels.newChannel(website.openStream());
                FileOutputStream fos = new FileOutputStream("song.mp3");

                fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);


            }
            catch(Exception e){

                System.out.println("got here");
                e.printStackTrace();
            }



            System.out.println("Done downloading...");


        }
    }
user3256520
  • 441
  • 1
  • 4
  • 17
  • 2
    how long did you wait for the exception? Because it SHOULD be thrown but since you disconnected physcially your operating system needs to wait until the socket-timeout for it to signal interruption ... this can take quite a few seconds, maybe even up to 30 – specializt Jul 26 '14 at 21:14
  • i see...let me try that. – user3256520 Jul 26 '14 at 21:14
  • i waited like 5 minutes and still it doesn't thrown an exception. It seems like it blocked forever. Do you think the timeout time could be more than 5 mins? – user3256520 Jul 26 '14 at 21:24
  • Why don't you explicitly specify timeout in your code,it'll surely work! @user3256520. – Am_I_Helpful Jul 26 '14 at 21:26
  • @shekharsuman do you mind telling me how can i set timeout? – user3256520 Jul 26 '14 at 21:28
  • 1
    unlikely. If your scenario doesnt yield an exception within a reasonable amount of time ... well ... either is your code faulty OR your used library (java.nio in your case) has defects. I think we're gonna go with the former possibility. Please post your actual code - all of it. – specializt Jul 26 '14 at 21:28
  • @specializt ok i have updated the post. Now, it has the actual code i am running. – user3256520 Jul 26 '14 at 21:32
  • btw http://b128.ve.vc/b/data/128/1735/asd.mp3 is invalid link ... i am using a valid link instead of that...i.e instead of asd.mp3 i have a name that is actually there which i thought not important to disclose. – user3256520 Jul 26 '14 at 21:33
  • @user3256520-Take help from this link--->`http://www.programcreek.com/java-api-examples/index.php?api=java.nio.channels.ReadableByteChannel`. – Am_I_Helpful Jul 26 '14 at 21:36
  • This question was partially asked again by the same user one day later: http://stackoverflow.com/questions/24983596/why-is-exception-not-thrown-when-the-connection-is-terminated. I believe that the answer given there also answers this question: http://stackoverflow.com/a/26747313/1070890. – Fabian Ritzmann Nov 05 '14 at 00:18

2 Answers2

0

apparently one is able to set a timeout on your socket, i think this article describes it : http://technfun.wordpress.com/2009/01/29/networking-in-java-non-blocking-nio-blocking-nio-and-io/

Your current thread blocks forever - and thats your root problem. So one possible solution would be to switch to asynchronous operations and/or to set your timeout

specializt
  • 1,913
  • 15
  • 26
  • ok i am not using sockets explicitly so i am assuming it is used by URL underneath...so is there no other way around this code other than changing it entirely and using sockets instead? – user3256520 Jul 26 '14 at 21:44
  • can you please run the code in your computer and let me know if you are also not getting the exception? I am trying to suspect if the problem is with my hardware. I am using a very old computer. – user3256520 Jul 26 '14 at 21:58
  • 1
    you can use this to create a socket-based connection via URL / HTTP : http://www.java2s.com/Code/Java/Network-Protocol/Grabbingapageusingsocket.htm – specializt Jul 26 '14 at 21:59
  • 1
    ok i changed the code a little bit so now the url connection has a timeout. URL website = new URL("http://b128.ve.vc/b/data/128/1735/asd.mp3"); URLConnection con = website.openConnection(); con.setReadTimeout(1000); ReadableByteChannel rbc = Channels.newChannel(con.getInputStream()); FileOutputStream fos = new FileOutputStream("song.mp3"); fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); – user3256520 Jul 26 '14 at 22:00
  • but another strange thing is it timesout correctly but doesn't throw the exception. The docs says it throws exception when timeout is fired. So, now i am really suspecting my hardware. – user3256520 Jul 26 '14 at 22:01
  • how do you know that your code reaches its timeout if no exception is thrown? – specializt Jul 26 '14 at 23:18
  • because i can set the timeout to the time i want and i was just checking with different times..for example i put 1000 then after 1 second it prints "Done Downloading..." without throwing exception. I tried different times. So, it is not throwing exception for some reason. – user3256520 Jul 26 '14 at 23:32
  • You don't need blocking NIO to set a read timeout, or asynchronous operation either. – user207421 Jul 27 '14 at 01:20
  • No 'better solution' required, just a *correct* solution. Don't use non-blocking mode when you set a timeout: as you appear to have grasped in your edit. It doesn't require any further elaboration. – user207421 Sep 28 '14 at 22:46
0

Since you are using HTTP, you would be best of using the Apache HttpClient project. org.apache.http.client.config.RequestConfig.Builder allows to set various timeout values that have no correspondence in java.net.URL and related classes. Especially setting a socket timeout would help in your case. You can then use org.apache.http.HttpEntity.writeTo to directly write the resource to a FileOutputStream.

Fabian Ritzmann
  • 1,345
  • 9
  • 20