I'm using a ThreadSafeClientConnManager to perform simultaneous requests in background threads on Android, set up with:
HttpParams params = new BasicHttpParams();
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
HttpProtocolParams.setContentCharset(params, HTTP.DEFAULT_CONTENT_CHARSET);
HttpProtocolParams.setUseExpectContinue(params, true);
SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
registry.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443));
ClientConnectionManager connman = new ThreadSafeClientConnManager(params, registry);
client = new DefaultHttpClient(connman, params);
And executing requests with (note that I'm using outh-signpost):
HttpGet request = new HttpGet("https://" + API_HOST + "/" + API_VERSION + path);
OAuthConsumer consumer = new CommonsHttpOAuthConsumer(key, secret);
consumer.sign(request);
HttpResponse response = client.execute(request);
The problem is that after a while I start getting
java.net.SocketException: The operation timed out
Do I need to do something to explicitly release the connection after the request?
From the usage guide of apache httpclient, you need to make sure to consume all content on any pooled resource to guarantee it returns to the pool to be available for other threads later on -
http://hc.apache.org/httpcomponents-core-4.0.1/tutorial/html/fundamentals.html#d0e244
In case there's an exception thrown by the underlying library, it is best to abort the HttpMethod that you were trying to run, in which case the connection will be terminated.
Related
In one of our old project we are using DefaultHttpClient for networking. its working fine below lollipop devices but in lollipop get request hangs execute method call.
We are creating HttpClient like this.
public static MyHttpClient createHttpClient(Context ctx) {
try {
if(mgr == null){
SSLSocketFactory sf = SSLSocketFactory.getSocketFactory();
sf.setHostnameVerifier(SSLSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
httpParameters = new BasicHttpParams();
HttpProtocolParams.setVersion(httpParameters, HttpVersion.HTTP_1_1);
HttpProtocolParams.setContentCharset(httpParameters, HTTP.UTF_8);
HttpConnectionParams.setConnectionTimeout(httpParameters, HOST_REACH_TIMEOUT);
HttpConnectionParams.setSoTimeout(httpParameters, HOST_REACH_TIMEOUT);
SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
registry.register(new Scheme("https", sf, 443));
mgr = new ThreadSafeClientConnManager(httpParameters, registry);
}
return new MyHttpClient(mgr, httpParameters);
} catch (Exception e) {
return new MyHttpClient(ctx);
}
}
We are also setting timeouts. Any idea why its freezing there and how we can fix that?
Edit: one more thing that i have missed. It only happens when we hit same URL 3rd time. First two times it works fine.
Instantiate every time a new mgr.
I reference this page and implement trust slef-certificate as follows,
SchemeRegistry schemeRegistry = new SchemeRegistry();
// http scheme
schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
// https scheme
schemeRegistry.register(new Scheme("https", new EasySSLSocketFactory(), 443));
HttpParams params = new BasicHttpParams();
params.setParameter(ConnManagerPNames.MAX_TOTAL_CONNECTIONS, 30);
params.setParameter(ConnManagerPNames.MAX_CONNECTIONS_PER_ROUTE, new ConnPerRouteBean(30));
params.setParameter(HttpProtocolParams.USE_EXPECT_CONTINUE, false);
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
ClientConnectionManager cm = new ThreadSafeClientConnManager(params, schemeRegistry);
The EasySSLSocketFactory is here, and the EasyX509TrustManager is here.
I found that it would have a lot of SSL hello handshake.
After my studies, this situation may be reduced by using SSLSessionCache.
I search in the forum, but the solution almost using normal ssl connecting not using trust self-certificate.
How can I use SSLSessionCache when I implement trust self-certificate in HttpClient?
I'm sending a post request to http://www.pgu.donland.ru/php/Login.php using HttpClient and want to get response like this:
<?xml version="1.0" encoding="utf-8"?><resp status="1" uD="John" UID="2" e=""/>
but unfortunately I keep getting:
<?xml version="1.0" encoding="utf-8"?>
<resp status="1" uD="" UID="" e=""/>
What is happening here?
I'm using a custom class with HttpClient client field in it and in my constructor I'm using these settings:
SchemeRegistry schemeRegistry = new SchemeRegistry();
schemeRegistry.register(new Scheme("http", PlainSocketFactory
.getSocketFactory(), 80));
schemeRegistry.register(new Scheme("https", new EasySSLSocketFactory(),
443));
HttpParams params = new BasicHttpParams();
params.setParameter(ConnManagerPNames.MAX_TOTAL_CONNECTIONS, 30);
params.setParameter(ConnManagerPNames.MAX_CONNECTIONS_PER_ROUTE,
new ConnPerRouteBean(30));
params.setParameter(HttpProtocolParams.USE_EXPECT_CONTINUE, false);
params.setParameter("http.socket.timeout", timeout * 1000);
params.setParameter("http.connection.timeout", timeout * 1000);
// params.setParameter("http.connection-manager.timeout", new
// Long(timeout * 1000));
params.setParameter("http.protocol.head-body-timeout", timeout * 1000);
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
ClientConnectionManager cm = new SingleClientConnManager(params,
schemeRegistry);
this.client = new DefaultHttpClient(cm, params);
Thanks for any help you can provide.
a problem is on the server side. Check Login.php code.
Well, Russian is not the easiest language for an italian but... It looks like the uD and UID parameters are echoed by the server after having received them as a user name/password (or a user key) from the client. Maybe you are not sending any userID or any username/password pair to the server so it cannot respond you in the expected way.
I'm doing a lot of http calls in my Android application. The http calls are synchronous for the most part. Every once in a while I'll get many 403 forbidden responses in a row, hitting the same URL. I do a login call directly before the call that results in a 403. The login call returns 200 ok. The 403s also happen more on newer Android platforms.
How I'm creating the client:
// Create and initialize HTTP parameters
HttpParams params = new BasicHttpParams();
ConnManagerParams.setMaxTotalConnections(params, 200);
ConnPerRoute cpr = new ConnPerRoute() {
public int getMaxForRoute(HttpRoute httpRoute) {
return 50;
}
};
ConnManagerParams.setMaxConnectionsPerRoute(params, cpr);
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
// Create and initialize scheme registry
SchemeRegistry schemeRegistry = new SchemeRegistry();
schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
// Create an HttpClient with the ThreadSafeClientConnManager.
ClientConnectionManager cm = new ThreadSafeClientConnManager(params, schemeRegistry);
_client = new DefaultHttpClient(cm, params);
The http call:
CookieStore cookie_store = HttpSupport.getCookieStoreInstance();
HttpContext http_context = HttpSupport.getHttpContextInstance();
HttpGet get = new HttpGet(StaticFields.DEVICES_RESOURCE);
http_context.setAttribute(ClientContext.COOKIE_STORE, cookie_store);
response = client.execute(get, http_context);
status_code = response.getStatusLine().getStatusCode();
I'm using a static CookieStore and HttpContext contained in my class HttpSupport.
I had seen a few examples in Android implement maybeCreateHttpClient(), especially in Google sample, which it does is to check if HttpClient object is instantiated, if not, instantiate it, and reuse it.
Why this approach? Is creating new HttpClient expensive?
Use a connection pool (eg. ThreadSafeClientConnManager) to manage your clients.
HttpParams params = new BasicHttpParams();
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
HttpProtocolParams.setContentCharset(params, HTTP.DEFAULT_CONTENT_CHARSET);
HttpProtocolParams.setUseExpectContinue(params, true);
SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
registry.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443));
ClientConnectionManager connman = new ThreadSafeClientConnManager(params, registry);
client = new DefaultHttpClient(connman, params);
client is a singleton object which can be reused, to fire a request:
HttpResponse response = client.execute(new HttpGet(URL));
A HttpClient is fairly large and complex object. You might make tens (or probably more) http calls in your app. If you created a new one for each http request you would quickly run into memory problems and would certainly notice garbage collection slow downs.
The http client is a generic component to help you make http calls, just reuse it. There is no reason not too.