HttpParams params = new BasicHttpParams();
ConnManagerParams.setMaxConnectionsPerRoute(params, new ConnPerRouteBean(100));
ConnManagerParams.setMaxTotalConnections(params, 100);
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
HttpProtocolParams.setUseExpectContinue(params, false);
HttpProtocolParams.setContentCharset(params, HTTP.DEFAULT_CONTENT_CHARSET);
HttpConnectionParams.setConnectionTimeout(params, CONNECTION_TIMEOUT);
HttpConnectionParams.setSoTimeout(params, REQUEST_TIMEOUT);
SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), PORT));
ThreadSafeClientConnManager cm = new ThreadSafeClientConnManager(params, registry);
client = new DefaultHttpClient(cm, params);
HttpClientParams.setCookiePolicy(client.getParams(), CookiePolicy.BROWSER_COMPATIBILITY);
When my app waits for several seconds, the next post will be failed because of the ClientProtocolException.
By wireshark, I find that android also use the previous tcp socket to execute the post, but that socket is ended with a FIN from the server. And the next several posts will succeed because a new socket establish.
is there anyone know how to solve the problem??
I had a similar problem. Try adding this line :
System.setProperty("http.keepAlive", "false");
before you make the connection. Might solve your problem.
Related
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 use connection for server connections as show bleow.
HttpParams params = new BasicHttpParams();
ConnManagerParams.setMaxTotalConnections(params, 10);
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);
params.setIntParameter(CoreConnectionPNames.SO_TIMEOUT, Integer.valueOf(60000));
params.setIntParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, Integer.valueOf(60000));
params.setBooleanParameter(CoreConnectionPNames.TCP_NODELAY, true);
//eate and initialize scheme registry
SchemeRegistry schemeRegistry = new SchemeRegistry();
schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
// Create an HttpClient with the ThreadSafeClientConnManager.
// This connection manager must be used if more than one thread will
// be using the HttpClient.
cm = new ThreadSafeClientConnManager(params, schemeRegistry);
httpClient = new DefaultHttpClient(cm, params);
ThreadSafeClientConnManager API says:
ThreadSafeClientConnManager maintains a maximum limit of connection on a per route
basis and in total. Per default this implementation will create no more than than
2 concurrent connections per given route and no more 20 connections in total. For many
real-world applications these limits may prove too constraining, especially if they use
HTTP as a transport protocol for their services. Connection limits, however, can be
adjusted using HTTP parameters.
How can I change the maximum connections per host to more than 2?
Thanks in advance!
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.
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.