17

I'm running into an issue when i try to use the HttpClient connecting to a url. The http connection is taking a longer time to timeout, even after i set a connection timeoout.

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

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

It works perfect most of the time. However, every once in while, the http connection runs for ever and ignore the setconnectiontimeout, especailly when the phone is connected to wifi, and the phone was idling.

So after the phone is idling, the first time i try to connect, the http connection ignores the setconnectiontimeout and runs forever, after i cancel it and try again, it works like charm everytime. But that one time that doesn't work it creates a threadtimeout error, i tried using a different thread, it works, but i know that the thread is running for long time.

I understand that the wifi goes to sleep on idle, but i dont understand why its ignoring the setconnectiontimeout.

Anyone can help, id really appreciated.

skaffman
  • 398,947
  • 96
  • 818
  • 769
Mark
  • 171
  • 1
  • 1
  • 4
  • What platform are you talking about? – Eugene Mayevski 'Callback Jan 02 '11 at 09:20
  • The HTTP connection might "ignore" its timeout because it genuinely thinks it's connected, e.g. the initial handshake succeeded but nothing more comes out of the pipe (or in your case, the air). Maybe your phone has a tendency to keep accepting connections but immediately forgetting about them when idle. Capturing and examining the individual frames exchanged before this problem occurs will probably tell a lot more. – Frédéric Hamidi Jan 02 '11 at 09:21

10 Answers10

9

Not sure if this helps you, however I think it's worth sharing here. While playing with the timeout stuff I found there is a third timeout type you can assign:

// 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);
}
Vit Khudenko
  • 28,288
  • 10
  • 63
  • 91
  • 1
    Android 2.01.First of all, thank you guys for your help.@Arhimed, i tried that, it didn't work thanks though. The problem only happens under one of these conditions: 1 - if my phone is connected to wifi, and the wifi has no internet access. the timeout is not being catched in this case and it takes about 30 seconds. 2_ if the phone is connected to wifi and the wifi has internet access. After the phone has been idling for atleast 2 minutes, the initail connection takes about 30 seconds to timeout. Every other attempt, works perfectly. – Mark Jan 03 '11 at 00:58
  • 1
    @Mark: if your app behaves the same as the native YouTube app, then I think you can sleep well (native apps are code by top pros who are able to use API as much as possible). Sometimes there are cases that are just out of our control. Another consoling note - 30 secs is not that much if, for instance, to compare to BlackBerry where you have 2 minutes and you can not change that. ;) – Vit Khudenko Jan 03 '11 at 11:24
1
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();

Is that along the lines of what you all are suggesting?

I'm not exactly sure how to cancel the execute once it has started, but this seemed to work for me. I'm not sure which of the three lines in the thread did the magic, or if it was some combination of all of them.

Cosmin
  • 21,216
  • 5
  • 45
  • 60
  • Actually, this doesn't seem to work either. Do I have to put the execute in its own thread, because I really don't want to do that. Is there no way to just kill it? – Randy Baden Mar 31 '11 at 18:40
1

I've met the same problem, I guess maybe the Android doesn't support this parameter. In my case i tested all three parameters for the 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 );

The first and second worked fine, but the third didn't work as documented. No exception was thrown and the executing thread was blocked indefinitely when the DefaultHttpClient#execute() was executing.

see http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html#d4e650
"...One can ensure the connection manager does not block indefinitely in the connection request operation by setting 'http.conn-manager.timeout' to a positive value. If the connection request cannot be serviced within the given time period ConnectionPoolTimeoutException will be thrown."

Chen Zhuo
  • 71
  • 5
0

The problem might be in the Apache HTTP Client. See HTTPCLIENT-1098. Fixed in 4.1.2.

The timeout exception tries to reverse DNS the IP, for logging purposes. This takes an additional time until the exception is actually fired.

noam
  • 101
  • 1
  • 5
0

You could manage the timeouts yourself, this way you can be confident that no matter what state the connection gets in, unless you receive an acceptable response, that your timeout will fire and the http request will be aborted.

Tyler
  • 2,699
  • 4
  • 22
  • 31
  • First of all, thank you guys for your help.@Arhimed, i tried that, it didn't work. – Mark Jan 03 '11 at 00:47
  • I ran a test, i connected my phone to a wifi that doesn't have internet, and i clicked on you tube app. it took 30 seconds to find out that there is no connection, just like my app. It's driving me crazy, the way its ignoring the timeout connection. – Mark Jan 03 '11 at 01:08
  • 1
    That's because on a wifi without access to the internet, if your URL is to a hostname and not a direct IP address, then the connection isn't even being made; all that time you're waiting is being spent trying to resolve de hostname. – Chochos Jan 04 '11 at 23:56
  • If Chochos is right, and I suspect he is, then Mark you could manage the DNS lookup yourself and more aggressively cache the IP if it doesn't change much. i.e. rather than using the hostname in the URI, you use the IP address from your cache. – Ollie C Jan 19 '11 at 16:47
0

I've had similar issues with timeouts on android. To resolve it what I did was used the commands to not let the phone idle while I was attempting to establish a connection and during any reads or writes to the connection. Its probably worth a shot in this case as well.

0

Although I haven't seen this on the Android platform, I've seen similar things on other platforms and the solution in these cases is to manage the timeout yourself. Kick off another thread (the timeout thread) when your make your request. The timeout thread counts down the requisite time. If the timeout expires before you receive any data, the timeout thread cancels the original request and you retry with a new request. Harder to code, but at least you know it will work.

Eric Giguere
  • 3,495
  • 15
  • 11
0

From you snippet it's not ultimately clear if you set the timeouts before calling HttpClient.executeMethod(..). So this is my guess.

Waldheinz
  • 10,399
  • 3
  • 31
  • 61
0

Well, if you idle/multitask to another application, then your thread that is running might be stopped and destroyed. Maybe you should put the connection code inside a Service instead?:

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

Marius K
  • 498
  • 5
  • 6
0

How are you making the HTTP Connection? This looks like a threading issue. If you are using a background thread, then the thread may be killed along with any timeout registered. The fact that it works the next time tells me that your code will work, if you make the call in a android component and manage the WAKE_LOCK on it yourself. Anyways please post more information about the calling mechanism?

uncaught_exceptions
  • 21,712
  • 4
  • 41
  • 48