HttpURLConnection setConnectTimeout() has no effect

前端 未结 8 1479
刺人心
刺人心 2020-12-04 21:40

I\'m connecting to a simple RSS feed using HTTPUrlConnection. It works perfectly. I\'d like to add a timeout to the connection since I don\'t want my app hanging in the even

相关标签:
8条回答
  • 2020-12-04 22:16

    I was facing the same issue. Setting the connectionTimeout and readTimeout does not seems to return the exception as expected, but take really. It took me while to check the URLConnection() Method and understand what is going on. In the documentation for setConnectTimeout there is a warning

    "if the hostname resolves to multiple IP addresses, this client will try each. If connecting to each of these addresses fails, multiple timeouts will elapse before the connect attempt throws an exception." This mean s if you have 10 ips resolved by your host your actual time out will "10*readTimeoutSet".

    You can check ips for the the host name here

    0 讨论(0)
  • 2020-12-04 22:22

    I had a similar problem - because the HttpUrlConnection won't time out mid-download. For example, if you turn off wifi when download is going, mine continued to say it is downloading, stuck at the same percentage.

    I found a solution, using a TimerTask, connected to a AsyncTask named DownloaderTask. Try:

    class Timeout extends TimerTask {
        private DownloaderTask _task;
    
        public Timeout(DownloaderTask task) {
            _task = task;
        }
    
        @Override
        public void run() {
            Log.w(TAG,"Timed out while downloading.");
            _task.cancel(false);
        }
    };
    

    Then in the actual download loop set a timer for timeout-error:

                        _outFile.createNewFile();
                        FileOutputStream file = new FileOutputStream(_outFile);
                        out = new BufferedOutputStream(file);
                        byte[] data = new byte[1024];
                        int count;
                        _timer = new Timer();
                        // Read in chunks, much more efficient than byte by byte, lower cpu usage.
                        while((count = in.read(data, 0, 1024)) != -1 && !isCancelled()) { 
                            out.write(data,0,count);
                            downloaded+=count;
                            publishProgress((int) ((downloaded/ (float)contentLength)*100));
                            _timer.cancel();
                            _timer = new Timer();
                            _timer.schedule(new Timeout(this), 1000*20);
                        }
                        _timer.cancel();
                        out.flush();
    

    If it times out, and won't download even 1K in 20 seconds, it cancels instead of appearing to be forever downloading.

    0 讨论(0)
  • 2020-12-04 22:25

    You should try to set the read timeout as well (http.setReadTimeout()). Oftentimes, a web server will happily accept your connection, but it might be slow in actually responding to the request.

    0 讨论(0)
  • 2020-12-04 22:27

    You probably either/both:
    1) Don't read anything from connection
    2) Don't catch & handle the exception properly

    As mentioned here, use logic similar to this:

    int TIMEOUT_VALUE = 1000;
    try {
        URL testUrl = new URL("http://google.com");
        StringBuilder answer = new StringBuilder(100000);
    
        long start = System.nanoTime();
    
        URLConnection testConnection = testUrl.openConnection();
        testConnection.setConnectTimeout(TIMEOUT_VALUE);
        testConnection.setReadTimeout(TIMEOUT_VALUE);
        BufferedReader in = new BufferedReader(new InputStreamReader(testConnection.getInputStream()));
        String inputLine;
    
        while ((inputLine = in.readLine()) != null) {
            answer.append(inputLine);
            answer.append("\n");
        }
        in.close();
    
        long elapsed = System.nanoTime() - start;
        System.out.println("Elapsed (ms): " + elapsed / 1000000);
        System.out.println("Answer:");
        System.out.println(answer);
    } catch (SocketTimeoutException e) {
        System.out.println("More than " + TIMEOUT_VALUE + " elapsed.");
    }
    
    0 讨论(0)
  • 2020-12-04 22:27

    Try to set the ConnectionTimeout before openning the connection.

    0 讨论(0)
  • 2020-12-04 22:30

    It's caused by:
    1. You are connected to wifi but you dont have internet connection.
    2. You are connected to GSM data but your transfer is very poor.

    In both cases you get a host exception after about 20seconds. In my opinion the best way to get correct is:

    public boolean isOnline() {
            final int TIMEOUT_MILLS = 3000;
            final boolean[] online = {false};
            ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
            NetworkInfo netInfo = cm.getActiveNetworkInfo();
            if (netInfo != null && netInfo.isConnected()) {
                final long time = System.currentTimeMillis();
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            URL url = new URL("http://www.google.com");
                            HttpURLConnection urlc = (HttpURLConnection) url.openConnection();
                            urlc.setConnectTimeout(TIMEOUT_MILLS);
                            urlc.setReadTimeout(TIMEOUT_MILLS);
                            urlc.connect();
                            if (urlc.getResponseCode() == 200) {
                                online[0] = true;
                            }
                        } catch (IOException e) {
                            loger.add(Loger.ERROR, e.toString());
                        }
                    }
                }).start();
    
                while (((System.currentTimeMillis() - time) <= TIMEOUT_MILLS)) {
                    if ((System.currentTimeMillis() - time) >= TIMEOUT_MILLS) {
                        return online[0];
                    }
                }
            }
            return online[0];
        }
    

    remember - use it in asynctask or service.

    Its simple solution, you are starting new Thread with HttpUrlConnection (remember use start() not run()). Than in while loop you are waiting 3 sec for result. If nothing happend return false. This way let you avoid waiting for host exception and avoid problem with not working setConnectTimeout() when you dont have internet connection.

    0 讨论(0)
提交回复
热议问题