【问题标题】:Android UnknownHostException : is there a way to set timeout?Android UnknownHostException:有没有办法设置超时?
【发布时间】:2012-03-08 23:35:02
【问题描述】:

当我连接到我的网络服务以检索数据时,电话有时会断开连接、DNS 混乱等。然后我得到一个 UnknownHostException,这非常好。

我要做的是在此处查找主机名时设置超时:

 response = httpclient.execute(httpget);

我已经设置好了:

HttpConnectionParams.setConnectionTimeout(httpParameters,timeoutConnection);
HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket);

但他们似乎没有申请HostLookUp。有没有办法在主机查找时设置超时?

编辑
刚刚发现用户无法修改nslookupin this post on the hc-dev mailing list的超时时间。

此时我将不得不手动从计时器中抛出超时异常。

【问题讨论】:

  • 请提供您的 Web 服务运行的 IP 地址,而不是域名。我也面临同样的问题。但是我的网络服务在本地机器上运行。所以当我给 localhost 它抛出一个异常。但它接受我的 IP 地址。

标签: java android httpclient


【解决方案1】:

首先 HttpParams httpParams = new BasicHttpParams() 被贬低, 使用这个 HttpURLConnection conn = (HttpURLConnection) url.openConnection();

当您的参数大小大于 2mb 时,服务器会给出超时响应。

检查您的参数大小并告诉我。

【讨论】:

    【解决方案2】:

    试试这个

    public class MyAsync extends AsyncTask<String, Integer, String> {
    
    
    @Override
    protected String doInBackground(String... arg0) {
         HttpParams httpParameters = new BasicHttpParams();
            // Set the timeout in milliseconds until a connection is established.
            int timeoutConnection = 3000;
            HttpConnectionParams.setConnectionTimeout(httpParameters, timeoutConnection);
            // Set the default socket timeout (SO_TIMEOUT) 
            // in milliseconds which is the timeout for waiting for data.
            int timeoutSocket = 5000;
            HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket);
        HttpClient client=new DefaultHttpClient(httpParameters);
        HttpGet get=new HttpGet(arg0[0]);
        try {
            HttpResponse response=client.execute(get);
            HttpEntity ent=response.getEntity();
            String res=EntityUtils.toString(ent);
            Log.d("Nzm", res);
    
        } catch (ClientProtocolException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }
    

    }

    【讨论】:

      【解决方案3】:
      DefaultHttpClient client = new DefaultHttpClient();
      
          HttpParams httpParameters = new BasicHttpParams();
          // Set the timeout in milliseconds until a connection is established.
          // The default value is zero, that means the timeout is not used. 
          int timeoutConnection = 30000;
          HttpConnectionParams.setConnectionTimeout(httpParameters, timeoutConnection);
      //      HttpConnectionParams.setHeader("Accept", "application/json");
      
          // Set the default socket timeout (SO_TIMEOUT) 
          // in milliseconds which is the timeout for waiting for data.
          int timeoutSocket = 30000;
          HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket);
      
          client.setParams(httpParameters);
      

      【讨论】:

        【解决方案4】:

        如果您使用线程进行网络操作会更好,然后您可以在外部设置超时。我曾使用此方法解决定义超时不起作用的问题。

        在这种方法中,后通信代码被编写在 Handler 中。我们可以通过发送消息来触发这个处理程序(我们也可以通过消息传递数据)。触发语句写在倒数计时器和线程中的通信代码之后。必要的代码被写在处理程序中以禁用更多的触发(通过为对象分配一个新的空处理程序),这样只有一个触发工作。

        如果您喜欢这个逻辑并且需要更多解释。请在下方评论

        【讨论】:

          【解决方案5】:

          你可以试试这样的:-

          URLConnection connection = null;
          connection =  address.openConnection();
          post = (HttpsURLConnection) connection;
          post.setSSLSocketFactory(context.getSocketFactory()); 
          post.setDoInput(true);
          post.setDoOutput(true);
          
          // Connecting to a server will fail with a SocketTimeoutException if the timeout     elapses before a connection is established
          post.setConnectTimeout(Const.CONNECTION_TIMEOUT_DELAY);
          post.setRequestMethod("POST");  // throws ProtocolException
          
          
          post.setRequestProperty("soapaction","");
          post.setRequestProperty("Content-Type", "text/xml; charset=utf-8");
          post.setRequestProperty("Authorization", "Basic " +         Base64.encodeToString(strCredentials.getBytes(), Base64.NO_WRAP));
                      post.setRequestProperty("Content-Length",           String.valueOf(requestEnvelope.length()));
          

          //如果在数据可用之前超时,读取将失败并抛出 SocketTimeoutException.. post.setReadTimeout(Const.READ_TIMEOUT_DELAY);

          【讨论】:

            【解决方案6】:

            对我来说,如果我们失去连接,则不会使用超时(测试:关闭 WiFi)。所以我写了一个方法,尝试下载文件最多 X 次,每次尝试之间等待 Y 毫秒:

            public static byte[] getByteArrayFromURL(String url, int maxTries, int intervalBetweenTries) throws IOException {
            
                try {
            
                    return Utils.getByteArrayFromURL(url);
                }
                catch(FileNotFoundException e) { throw e; }
                catch(IOException e) {
            
                    if(maxTries > 0) {
            
                        try {
                            Thread.sleep(intervalBetweenTries);
                            return getByteArrayFromURL(url, maxTries - 1, intervalBetweenTries);
                        }
                        catch (InterruptedException e1) {
            
                            return getByteArrayFromURL(url, maxTries -1, intervalBetweenTries);
                        }
                    }
                    else {
            
                        throw e;
                    }
                }
            }
            

            这是下载文件并抛出 UnknownHostException 的方法:

            public static byte[] getByteArrayFromURL(String urlString) throws IOException {
            
                ByteArrayOutputStream out = new ByteArrayOutputStream();
                InputStream in = null;
                try {
            
                    in = new URL(urlString).openStream();
                    byte[] byteChunk = new byte[BUFFER_SIZE];
                    int n;
            
                    while ((n = in.read(byteChunk)) > 0) {
                        out.write(byteChunk, 0, n);
                    }
                }
                finally {
                    if (in != null) {
                        try { in.close(); }
                        catch (IOException e) { e.printStackTrace(); }
                    }
                }
            
                return out.toByteArray();
            }
            

            现在,如果您要下载的文件不存在,该方法将立即失败,否则如果抛出 IOException(如 UnknownHostException),它将重试,直到“maxTries”,等待“intervalBetweenTries”每次尝试之间。

            当然,你必须异步使用它。

            【讨论】:

              【解决方案7】:

              我发现 Volley(我会说是 AsyncTask 的替换)库更易于使用,并且错误更少。如果您使用 volley,则更容易管理超时。但是,关于您的问题,

                response = httpclient.execute(httpget);
              

              我想你正在使用 AsyncTask。 httpconnection 中也有settimeout() 的选项,但由于DNS 的问题,它不能正常工作。所以尝试使用runnable() 并设置时间。我在我的一个项目中使用了这种方法,早在还没有使用 Volley 的时候。

              希望这会有所帮助。

              【讨论】:

                【解决方案8】:

                试试这个,也许对你有帮助。

                final HttpParams httpParams = new BasicHttpParams()
                
                
                HttpConnectionParams.setConnectionTimeout(httpParams, 1000)
                
                
                HttpConnectionParams.setSoTimeout(httpParams, 30000) 
                
                HttpClient hc = new DefaultHttpClient(httpParams)
                
                try
                 {
                
                
                 HttpGet get = new HttpGet("http://www.google.com")
                
                  HttpResponse response = hc.execute(get)
                
                  take your response now.
                

                }

                【讨论】:

                  【解决方案9】:

                  你应该使用这样的东西:

                  /**
                   * Check availability of web service
                   * 
                   * @param host Address of host
                   * @param seconds Timeout in seconds
                   * @return Availability of host
                   */
                  public static boolean checkIfURLExists(String host, int seconds)
                  {
                      HttpURLConnection httpUrlConn;
                      try
                      {
                          httpUrlConn = (HttpURLConnection) new URL(host).openConnection();
                  
                          // Set timeouts in milliseconds
                          httpUrlConn.setConnectTimeout(seconds * 1000);
                          httpUrlConn.setReadTimeout(seconds * 1000);
                  
                          // Print HTTP status code/message for your information.
                          System.out.println("Response Code: " + httpUrlConn.getResponseCode());
                          System.out.println("Response Message: "
                                  + httpUrlConn.getResponseMessage());
                  
                          return (httpUrlConn.getResponseCode() == HttpURLConnection.HTTP_OK);
                      }
                      catch (Exception e)
                      {
                          System.out.println("Error: " + e.getMessage());
                          return false;
                      }
                  }
                  

                  【讨论】:

                  • setConnectTimeout 和 setReadTimeout 不适用于 DNS 解析运行时...这就是问题
                  【解决方案10】:

                  请下载此 Jar 文件并导入 lib 文件夹 http://grepcode.com/snapshot/repo1.maven.org/maven2/org.apache.httpcomponents/httpmime/4.2.1 并继续运行您的应用程序..您的代码是正确的

                  【讨论】:

                    【解决方案11】:

                    您可以向您的服务器发送 ping 请求并设置 ping 请求的超时时间。如果为真,您有互联网连接,如果为假,则什么也不做。代码应如下所示:

                    public static boolean connection() throws UnknownHostException, IOException {
                        String ipAddress = "94.103.35.164";
                        InetAddress inet = InetAddress.getByName(ipAddress);
                    
                        if(inet.isReachable(1000)){
                            return true;
                        }
                        else {
                            return false;
                        }
                    }
                    

                    您可以在此示例中更改您的超时时间。我设置了 1 秒超时。

                    【讨论】:

                      【解决方案12】:

                      是的,您可以按照以下步骤设置超时

                      1. 进入eclipse的window->preferences->Android->DDMS,增加ADB连接超时时间。

                      【讨论】:

                      • -1:weakwire 正在谈论他的应用程序中的超时——而不是在 ADB 连接中。
                      猜你喜欢
                      • 1970-01-01
                      • 2010-09-17
                      • 1970-01-01
                      • 2013-11-15
                      • 2011-03-19
                      • 2019-10-14
                      • 2019-10-21
                      • 2019-05-30
                      • 2016-07-16
                      相关资源
                      最近更新 更多