【问题标题】:http connection timeout issueshttp连接超时问题
【发布时间】:2011-06-02 10:40:08
【问题描述】:

当我尝试使用 HttpClient 连接时遇到问题 到一个网址。即使在我设置之后,http 连接也需要更长的时间才能超时 连接超时。

int timeoutConnection = 5000;
HttpConnectionParams.setConnectionTimeout(httpParameters, timeoutConnection);

int timeoutSocket = 5000;
HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket);

它在大多数情况下都能完美运行。但是,每隔一段时间,http 连接就会永远运行并忽略setconnectiontimeout,尤其是当手机连接到 wifi 并且手机处于空闲状态时。

所以在手机空闲后,我第一次尝试连接时,http 连接会忽略setconnectiontimeout 并永远运行,在我取消它并重试后,它每次都像魅力一样工作。但是那一次不起作用它会创建一个threadtimeout 错误,我尝试使用不同的线程,它可以工作,但我知道该线程运行了很长时间。

我知道 wifi 在空闲时进入睡眠状态,但我不明白为什么它会忽略 setconnectiontimeout

任何人都可以提供帮助,我真的很感激。

【问题讨论】:

  • 你说的是什么平台?
  • HTTP 连接可能会“忽略”它的超时,因为它真的认为它已连接,例如最初的握手成功了,但管道(或者在你的情况下,空气)中没有任何东西。也许您的手机倾向于继续接受连接,但在空闲时立即忘记它们。捕获并检查在此问题发生之前交换的各个帧可能会提供更多信息。

标签: java android timeout apache-httpclient-4.x


【解决方案1】:

问题可能出在 Apache HTTP 客户端中。见HTTPCLIENT-1098。 已在 4.1.2 中修复。

超时异常尝试反向 DNS IP,以进行日志记录。这需要额外的时间才能真正触发异常。

【讨论】:

    【解决方案2】:
    Thread t=new Thread()
    {
      public void run()
      {
        try 
        {
          Thread.sleep(absolutetimeout);
          httpclient.getConnectionManager().closeExpiredConnections();
          httpclient.getConnectionManager().closeIdleConnections(absolutetimeout,TimeUnit.MILLISECONDS);
          httpclient.getConnectionManager().shutdown();
          log.debug("We shutdown the connection manager!");
        }
        catch(InterruptedException e)
        {}
      }
    };
    
    t.start();
    HttpResponse res= httpclient.execute(httpget);
    t.interrupt();
    

    这是否符合你们所有人的建议?

    我不确定如何在执行开始后取消执行,但这似乎对我有用。我不确定线程​​中的三行中的哪一行起到了神奇的作用,或者它是否是所有这些行的某种组合。

    【讨论】:

    • 实际上,这似乎也不起作用。我是否必须将执行放在自己的线程中,因为我真的不想这样做。有没有办法直接杀死它?
    【解决方案3】:

    我也遇到了同样的问题,我猜可能是安卓不支持这个参数。 就我而言,我测试了 ThreadSafeClientConnManager 的所有三个参数

    params.setParameter( ConnManagerPNames.MAX_CONNECTIONS_PER_ROUTE, new ConnPerRouteBean(20) );
    params.setIntParameter( ConnManagerPNames.MAX_TOTAL_CONNECTIONS, 200 );
    params.setLongParameter( ConnManagerPNames.TIMEOUT, 10 );
    ThreadSafeClientConnManager connmgr = new ThreadSafeClientConnManager( params );
    

    第一个和第二个工作正常,但第三个没有按记录工作。 DefaultHttpClient#execute() 执行时没有抛出异常,执行线程被无限期阻塞。

    http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html#d4e650
    “...可以通过将'http.conn-manager.timeout'设置为正值来确保连接管理器不会无限期阻塞连接请求操作。如果在给定的时间段内无法处理连接请求,ConnectionPoolTimeoutException将是扔了。”

    【讨论】:

      【解决方案4】:

      你是如何建立 HTTP 连接的?这看起来像一个线程问题。如果您使用的是后台线程,则该线程可能会与注册的任何超时一起被终止。它下次工作的事实告诉我,如果你在一个 android 组件中进行调用并自己管理它的 WAKE_LOCK,你的代码将工作。无论如何,请发布有关调用机制的更多信息?

      【讨论】:

        【解决方案5】:

        好吧,如果您空闲/多任务处理另一个应用程序,那么您正在运行的线程可能会停止并销毁。也许您应该将连接代码放在服务中?:

        http://developer.android.com/reference/android/os/AsyncTask.html http://developer.android.com/reference/android/app/IntentService.html

        【讨论】:

          【解决方案6】:

          从你的 sn-p 来看,如果你在调用HttpClient.executeMethod(..) 之前设置超时,最终并不清楚。所以这是我的猜测。

          【讨论】:

            【解决方案7】:

            虽然我没有在 Android 平台上看到过这种情况,但我在其他平台上也看到过类似的情况,在这些情况下的解决方案是自己管理超时。当您提出请求时,启动另一个线程(超时线程)。超时线程倒计时所需时间。如果超时在您收到任何数据之前到期,超时线程会取消原始请求,然后您重试新请求。更难编码,但至少你知道它会工作。

            【讨论】:

              【解决方案8】:

              我在 android 上遇到过类似的超时问题。为了解决这个问题,我在尝试建立连接以及对连接进行任何读取或写入操作时使用了命令不要让手机空闲。在这种情况下,它可能也值得一试。

              【讨论】:

                【解决方案9】:

                不确定这是否对您有帮助,但我认为值得在这里分享。在玩超时的东西时,我发现你可以分配第三种超时类型:

                // the timeout until a connection is established
                private static final int CONNECTION_TIMEOUT = 5000; /* 5 seconds */
                
                // the timeout for waiting for data
                private static final int SOCKET_TIMEOUT = 5000; /* 5 seconds */
                
                // ----------- this is the one I am talking about:
                // the timeout until a ManagedClientConnection is got 
                // from ClientConnectionRequest
                private static final long MCC_TIMEOUT = 5000; /* 5 seconds */
                
                ...
                
                HttpGet httpGet = new HttpGet(url);
                setTimeouts(httpGet.getParams());
                
                ...
                
                private static void setTimeouts(HttpParams params) {
                    params.setIntParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 
                        CONNECTION_TIMEOUT);
                    params.setIntParameter(CoreConnectionPNames.SO_TIMEOUT, SOCKET_TIMEOUT);
                    params.setLongParameter(ConnManagerPNames.TIMEOUT, MCC_TIMEOUT);
                }
                

                【讨论】:

                • Android 2.01。首先,感谢你们的帮助。@Arhimed,我试过了,不过还是不行,谢谢。该问题仅在以下条件之一下发生: 1 - 如果我的手机连接到 wifi,并且 wifi 无法访问互联网。在这种情况下超时没有被捕获,大约需要 30 秒。 2_如果手机连接到wifi并且wifi可以上网。手机闲置至少 2 分钟后,初始连接大约需要 30 秒才能超时。其他所有尝试都完美无缺。
                • @Mark:如果您的应用程序的行为与原生 YouTube 应用程序相同,那么我认为您可以睡个好觉(原生应用程序是由能够尽可能使用 API 的顶级专业人员编写的代码)。有时有些情况是我们无法控制的。另一个安慰说明 - 30 秒并不多,例如,如果与 BlackBerry 相比,您有 2 分钟并且您无法更改它。 ;)
                【解决方案10】:

                您可以自己管理超时,这样您就可以确信无论连接处于何种状态,除非您收到可接受的响应,否则您的超时将触发并且 http 请求将被中止。

                【讨论】:

                • 首先,谢谢大家的帮助。@Arhimed,我试过了,没用。
                • 我进行了测试,我将手机连接到没有互联网的 wifi,然后我点击了你的管应用程序。花了 30 秒才发现没有连接,就像我的应用程序一样。它让我发疯,它忽略超时连接的方式。
                • 这是因为在无法访问互联网的 wifi 上,如果您的 URL 指向主机名而不是直接 IP 地址,则连接甚至不会建立;您等待的所有时间都花在尝试解析主机名上。
                • 如果 Chochos 是对的,我怀疑他是对的,那么 Mark 你可以自己管理 DNS 查找,如果 IP 没有太大变化,可以更积极地缓存 IP。即,您使用缓存中的 IP 地址,而不是在 URI 中使用主机名。
                猜你喜欢
                • 2018-10-12
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2011-09-04
                • 2019-12-30
                • 1970-01-01
                • 2014-03-11
                相关资源
                最近更新 更多