Android UnknownHostException:有没有办法设置超时?

Posted

技术标签:

【中文标题】Android UnknownHostException:有没有办法设置超时?【英文标题】:Android UnknownHostException : is there a way to set timeout? 【发布时间】: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 地址。 【参考方案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】:

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

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

【讨论】:

-1:weakwire 正在谈论他的应用程序中的超时——而不是在 ADB 连接中。

以上是关于Android UnknownHostException:有没有办法设置超时?的主要内容,如果未能解决你的问题,请参考以下文章

Android 逆向Android 权限 ( Android 逆向中使用的 android.permission 权限 | Android 系统中的 Linux 用户权限 )

android 21 是啥版本

Android逆向-Android基础逆向(2-2)

【Android笔记】android Toast

图解Android - Android核心机制

Android游戏开发大全的目录