【问题标题】:HttpURLConnection setConnectTimeout() has no effectHttpURLConnection setConnectTimeout() 没有效果
【发布时间】:2011-07-26 12:11:35
【问题描述】:

我正在使用 HTTPUrlConnection 连接到一个简单的 RSS 提要。它完美地工作。我想为连接添加超时,因为我不希望我的应用程序在连接不良或其他情况下挂起。这是我使用的代码,setConnectTimeout 方法没有任何作用。

        HttpURLConnection http = (HttpURLConnection) mURL.openConnection();
        http.setConnectTimeout(15000); //timeout after 15 seconds
...

如果它有助于我在 android 上开发。

【问题讨论】:

  • 两件事供您考虑。如果您不希望您的应用程序挂起,请将您的连接方法放在单独的线程中。其次,你说它“工作得很好”,你在做什么来模拟一个坏的连接?
  • @Otra 我使用进度对话框将它放在单独的线程中。基本上发生的情况是,如果连接良好,任务就会完成它的工作。但是如果连接不好,进度对话框会持续很长时间。为了模拟不良连接,我正在减少超时时间。而不是给它 15 秒,1 秒。只是为了测试。还是说错了?
  • HttpURLConnection.setReadTimeout(mili sec);
  • @JonSnow 请分享完整的网络连接代码

标签: java android


【解决方案1】:

您也应该尝试设置读取超时 (http.setReadTimeout())。通常,Web 服务器会很乐意接受您的连接,但实际响应请求时可能会很慢。

【讨论】:

  • 如果连接到路由器但互联网连接中断,则对我不起作用。
【解决方案2】:

您可能两者兼有:
1)不要从连接中读取任何内容
2)不要正确捕获和处理异常

here所述,使用类似这样的逻辑:

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.");
}

【讨论】:

    【解决方案3】:

    我遇到了类似的问题 - 因为 HttpUrlConnection won't time out 下载中途。比如你在下载的时候关掉wifi,我的继续说正在下载,一直卡在同一个百分比。

    我找到了一个解决方案,使用 TimerTask,连接到名为 DownloaderTask 的 AsyncTask。试试:

    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);
        }
    };
    

    然后在实际的下载循环中为 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();
    

    如果超时,并且在 20 秒内甚至无法下载 1K,它就会取消,而不是看起来永远在下载。

    【讨论】:

      【解决方案4】:

      我遇到了同样的问题。设置connectionTimeoutreadTimeout 似乎并没有按预期返回异常,但确实如此。我花了一段时间检查URLConnection() 方法并了解发生了什么。在setConnectTimeout 的文档中有一个警告

      “如果主机名解析为多个 IP 地址,此客户端将尝试每个。如果连接到这些地址中的每一个都失败,则在连接尝试引发异常之前将经过多次超时。” 这意味着如果您的主机解析了 10 个 ip,您的实际超时将是“10*readTimeoutSet”。

      您可以检查主机名here的ips

      【讨论】:

        【解决方案5】:
        http.setConnectTimeout(15000);
        http.setReadTimeout(15000);
        

        【讨论】:

          【解决方案6】:

          这是由于:
          1.您已连接到wifi,但您没有互联网连接。
          2.您已连接到GSM数据,但您的传输很差。

          在这两种情况下,您都会在大约 20 秒后收到主机异常。在我看来,正确的最好方法是:

          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];
              }
          

          记住 - 在异步任务或服务中使用它。

          它的简单解决方案,您正在使用 HttpUrlConnection 启动新线程(请记住使用 start() 而不是 run())。比在 while 循环中你等待 3 秒的结果。如果什么都没发生,则返回 false。这样可以避免等待主机异常,并避免在没有互联网连接时 setConnectTimeout() 无法工作的问题。

          【讨论】:

            【解决方案7】:

            零值意味着无限超时,这意味着必须发生连接,通常为零是默认值:

            connection.setConnectTimeout(0);
            connection.setReadTimeout(0);
            

            参考here

            【讨论】:

              【解决方案8】:

              尝试在打开连接之前设置ConnectionTimeout

              【讨论】:

              • 怎么 - 构造函数是受保护的方法?
              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2012-12-04
              • 1970-01-01
              • 2016-02-02
              • 1970-01-01
              • 2012-10-30
              • 2018-05-21
              相关资源
              最近更新 更多