【问题标题】:How to set HttpResponse timeout for Android in Java如何在 Java 中为 Android 设置 HttpResponse 超时
【发布时间】:2010-10-16 04:36:33
【问题描述】:

我创建了以下检查连接状态的函数:

private void checkConnectionStatus() {
    HttpClient httpClient = new DefaultHttpClient();

    try {
      String url = "http://xxx.xxx.xxx.xxx:8000/GaitLink/"
                   + strSessionString + "/ConnectionStatus";
      Log.d("phobos", "performing get " + url);
      HttpGet method = new HttpGet(new URI(url));
      HttpResponse response = httpClient.execute(method);

      if (response != null) {
        String result = getResponse(response.getEntity());
        ...

当我关闭服务器以测试执行时,在线等待很长时间

HttpResponse response = httpClient.execute(method);

有谁知道如何设置超时以避免等待太久?

谢谢!

【问题讨论】:

    标签: java android timeout httpresponse


    【解决方案1】:

    在我的示例中,设置了两个超时。连接超时抛出java.net.SocketTimeoutException: Socket is not connected,套接字超时抛出java.net.SocketTimeoutException: The operation timed out

    HttpGet httpGet = new HttpGet(url);
    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 = 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);
    
    DefaultHttpClient httpClient = new DefaultHttpClient(httpParameters);
    HttpResponse response = httpClient.execute(httpGet);
    

    如果您想设置任何现有 HTTPClient 的参数(例如 DefaultHttpClient 或 AndroidHttpClient),您可以使用函数 setParams()

    httpClient.setParams(httpParameters);
    

    【讨论】:

    • @Thomas:我已经为您的用例编辑了我的答案
    • 如果连接超时,HttpResponse 会返回什么?在发出我的 HTTP 请求的那一刻,我会在调用返回时检查状态代码,但是如果调用超时,我会在检查此代码时得到 NullPointerException ......基本上,我该如何处理调用时的情况超时吗? (我使用的代码与您给出的答案非常相似)
    • @jellyfish - 尽管有文档,AndroidHttpClient 确实 扩展 DefaultHttpClient;相反,它实现了 HttpClient。您需要使用 DefaultHttpClient 才能使用 setParams(HttpParams) 方法。
    • 大家好,感谢您的出色回答。但是,我想在连接超时时向用户敬酒......我可以通过什么方式检测连接何时超时?
    • 不起作用。我在我的 Sony 和 Moto 上进行了测试,它们都被塞住了。
    【解决方案2】:

    在客户端设置设置:

    AndroidHttpClient client = AndroidHttpClient.newInstance("Awesome User Agent V/1.0");
    HttpConnectionParams.setConnectionTimeout(client.getParams(), 3000);
    HttpConnectionParams.setSoTimeout(client.getParams(), 5000);
    

    我已经在 J​​ellyBean 上成功使用了它,但也应该适用于旧平台 ....

    HTH

    【讨论】:

    • 和HttpClient是什么关系?
    【解决方案3】:

    如果您使用的是 Jakarta 的 http client library,那么您可以执行以下操作:

            HttpClient client = new HttpClient();
            client.getParams().setParameter(HttpClientParams.CONNECTION_MANAGER_TIMEOUT, new Long(5000));
            client.getParams().setParameter(HttpClientParams.SO_TIMEOUT, new Integer(5000));
            GetMethod method = new GetMethod("http://www.yoururl.com");
            method.getParams().setParameter(HttpMethodParams.SO_TIMEOUT, new Integer(5000));
            method.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,
            int statuscode = client.executeMethod(method);
    

    【讨论】:

    • HttpClientParams.CONNECTION_MANAGER_TIMEOUT 未知
    • 您应该使用 client.getParams().setIntParameter(..) 作为 *_TIMEOUT 参数
    • 如何找到?设备已连接到 wifi,但实际上没有通过 wifi 获取活动数据。
    【解决方案4】:

    如果您使用的是默认 http 客户端,以下是使用默认 http 参数的方法:

    HttpClient client = new DefaultHttpClient();
    HttpParams params = client.getParams();
    HttpConnectionParams.setConnectionTimeout(params, 3000);
    HttpConnectionParams.setSoTimeout(params, 3000);
    

    原始版权归http://www.jayway.com/2009/03/17/configuring-timeout-with-apache-httpclient-40/

    【讨论】:

      【解决方案5】:

      对于那些说@kuester2000的回答不起作用的人,请注意HTTP请求,首先尝试通过DNS请求找到主机IP,然后向服务器发出实际的HTTP请求,因此您可能还需要为 DNS 请求设置超时。

      如果您的代码在 DNS 请求没有超时的情况下工作,那是因为您能够访问 DNS 服务器,或者您正在访问 Android DNS 缓存。顺便说一句,你可以通过重启设备来清除这个缓存。

      此代码扩展了原始答案以包含具有自定义超时的手动 DNS 查找:

      //Our objective
      String sURL = "http://www.google.com/";
      int DNSTimeout = 1000;
      int HTTPTimeout = 2000;
      
      //Get the IP of the Host
      URL url= null;
      try {
           url = ResolveHostIP(sURL,DNSTimeout);
      } catch (MalformedURLException e) {
          Log.d("INFO",e.getMessage());
      }
      
      if(url==null){
          //the DNS lookup timed out or failed.
      }
      
      //Build the request parameters
      HttpParams params = new BasicHttpParams();
      HttpConnectionParams.setConnectionTimeout(params, HTTPTimeout);
      HttpConnectionParams.setSoTimeout(params, HTTPTimeout);
      
      DefaultHttpClient client = new DefaultHttpClient(params);
      
      HttpResponse httpResponse;
      String text;
      try {
          //Execute the request (here it blocks the execution until finished or a timeout)
          httpResponse = client.execute(new HttpGet(url.toString()));
      } catch (IOException e) {
          //If you hit this probably the connection timed out
          Log.d("INFO",e.getMessage());
      }
      
      //If you get here everything went OK so check response code, body or whatever
      

      使用方法:

      //Run the DNS lookup manually to be able to time it out.
      public static URL ResolveHostIP (String sURL, int timeout) throws MalformedURLException {
          URL url= new URL(sURL);
          //Resolve the host IP on a new thread
          DNSResolver dnsRes = new DNSResolver(url.getHost());
          Thread t = new Thread(dnsRes);
          t.start();
          //Join the thread for some time
          try {
              t.join(timeout);
          } catch (InterruptedException e) {
              Log.d("DEBUG", "DNS lookup interrupted");
              return null;
          }
      
          //get the IP of the host
          InetAddress inetAddr = dnsRes.get();
          if(inetAddr==null) {
              Log.d("DEBUG", "DNS timed out.");
              return null;
          }
      
          //rebuild the URL with the IP and return it
          Log.d("DEBUG", "DNS solved.");
          return new URL(url.getProtocol(),inetAddr.getHostAddress(),url.getPort(),url.getFile());
      }   
      

      本课程来自this blog post。用的话去看看备注吧。

      public static class DNSResolver implements Runnable {
          private String domain;
          private InetAddress inetAddr;
      
          public DNSResolver(String domain) {
              this.domain = domain;
          }
      
          public void run() {
              try {
                  InetAddress addr = InetAddress.getByName(domain);
                  set(addr);
              } catch (UnknownHostException e) {
              }
          }
      
          public synchronized void set(InetAddress inetAddr) {
              this.inetAddr = inetAddr;
          }
          public synchronized InetAddress get() {
              return inetAddr;
          }
      }
      

      【讨论】:

        【解决方案6】:

        一个选项是使用来自 Square 的 OkHttp 客户端。

        添加库依赖

        在 build.gradle 中,包含以下行:

        compile 'com.squareup.okhttp:okhttp:x.x.x'
        

        x.x.x 是所需的库版本。

        设置客户端

        例如,如果您想设置 60 秒的超时时间,请这样做:

        final OkHttpClient okHttpClient = new OkHttpClient();
        okHttpClient.setReadTimeout(60, TimeUnit.SECONDS);
        okHttpClient.setConnectTimeout(60, TimeUnit.SECONDS);
        

        ps:如果你的 minSdkVersion 大于 8,你可以使用TimeUnit.MINUTES。所以,你可以简单地使用:

        okHttpClient.setReadTimeout(1, TimeUnit.MINUTES);
        okHttpClient.setConnectTimeout(1, TimeUnit.MINUTES);
        

        有关单位的更多详细信息,请参阅TimeUnit

        【讨论】:

        【解决方案7】:
        HttpParams httpParameters = new BasicHttpParams();
                    HttpProtocolParams.setVersion(httpParameters, HttpVersion.HTTP_1_1);
                    HttpProtocolParams.setContentCharset(httpParameters,
                            HTTP.DEFAULT_CONTENT_CHARSET);
                    HttpProtocolParams.setUseExpectContinue(httpParameters, true);
        
                    // Set the timeout in milliseconds until a connection is
                    // established.
                    // The default value is zero, that means the timeout is not used.
                    int timeoutConnection = 35 * 1000;
                    HttpConnectionParams.setConnectionTimeout(httpParameters,
                            timeoutConnection);
                    // Set the default socket timeout (SO_TIMEOUT)
                    // in milliseconds which is the timeout for waiting for data.
                    int timeoutSocket = 30 * 1000;
                    HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket);
        

        【讨论】:

        • 不完整。和HttpClient是什么关系?
        【解决方案8】:

        你可以通过Httpclient-android-4.3.5的方式创建HttpClient实例,它可以很好地工作。

         SSLContext sslContext = SSLContexts.createSystemDefault();
                SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
                        sslContext,
                        SSLConnectionSocketFactory.STRICT_HOSTNAME_VERIFIER);
                        RequestConfig.Builder requestConfigBuilder = RequestConfig.custom().setCircularRedirectsAllowed(false).setConnectionRequestTimeout(30*1000).setConnectTimeout(30 * 1000).setMaxRedirects(10).setSocketTimeout(60 * 1000);
                CloseableHttpClient hc = HttpClients.custom().setSSLSocketFactory(sslsf).setDefaultRequestConfig(requestConfigBuilder.build()).build();
        

        【讨论】:

          【解决方案9】:

          如果您使用的是HttpURLConnection,请按照here 的说明致电setConnectTimeout()

          URL url = new URL(myurl);
          HttpURLConnection conn = (HttpURLConnection) url.openConnection();
          conn.setConnectTimeout(CONNECT_TIMEOUT);
          

          【讨论】:

          • 描述更像是建立连接的超时时间,而不是http请求?
          【解决方案10】:
          public boolean isInternetWorking(){
              try {
                  int timeOut = 5000;
                  Socket socket = new Socket();
                  SocketAddress socketAddress = new InetSocketAddress("8.8.8.8",53);
                  socket.connect(socketAddress,timeOut);
                  socket.close();
                  return true;
              } catch (IOException e) {
                  //silent
              }
              return false;
          }
          

          【讨论】:

          • 它代表哪个服务器? "8.8.8.8",53
          猜你喜欢
          • 2012-11-13
          • 2018-07-08
          • 2015-08-24
          • 2012-10-26
          • 2017-07-06
          • 1970-01-01
          • 2011-09-27
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多