Nor*_*ain 19 android httpclient
我正在努力解决以下问题:我的应用程序使用HttpClient向http服务器发出一系列请求.我使用HttpPut将数据发送到服务器.第一个请求进行得很快,第二个请求挂起40秒,然后我抓住Connection超时异常.我正在尝试重用我的HttpClient并通过同一个实例发送第二个请求.如果我与新的ConnectionManager一起创建新的HttpClient,那么一切正常.
为什么会这样?以及如何修复它并且每次都不创建新的HttpClient?
提前致谢.
这是我的代码:(如果我在doPut中评论readClient = newHttpClient(readClient),那么问题就出现了.
public class WebTest
{
private HttpClient readClient;
private SchemeRegistry httpreg;
private HttpParams params;
private URI url; //http://my_site.net/data/
protected HttpClient newHttpClient(HttpClient oldClient)
{
if(oldClient != null)
oldClient.getConnectionManager().shutdown();
ClientConnectionManager cm = new SingleClientConnManager(params, httpreg);
return new DefaultHttpClient(cm, params);
}
protected String doPut(String data)
{
//****************************
//Every time we need to send data, we do new connection
//with new ConnectionManager and close old one
readClient = newHttpClient(readClient);
//*****************************
String responseS = null;
HttpPut put = new HttpPut(url);
try
{
HttpEntity entity = new StringEntity(data, "UTF-8");
put.setEntity(entity);
put.setHeader("Content-Type", "application/json; charset=utf-8");
put.setHeader("Accept", "application/json");
put.setHeader("User-Agent", "Apache-HttpClient/WebTest");
responseS = readClient.execute(put, responseHandler);
}
catch(IOException exc)
{
//error handling here
}
return responseS;
}
public WebTest()
{
httpreg = new SchemeRegistry();
Scheme sch = new Scheme("http", PlainSocketFactory.getSocketFactory(), 80);
httpreg.register(sch);
params = new BasicHttpParams();
ConnPerRoute perRoute = new ConnPerRouteBean(10);
ConnManagerParams.setMaxConnectionsPerRoute(params, perRoute);
ConnManagerParams.setMaxTotalConnections(params, 50);
ConnManagerParams.setTimeout(params, 15000);
int timeoutConnection = 15000;
HttpConnectionParams.setConnectionTimeout(params, timeoutConnection);
// Set the default socket timeout (SO_TIMEOUT)
// in milliseconds which is the timeout for waiting for data.
int timeoutSocket = 40000;
HttpConnectionParams.setSoTimeout(params, timeoutSocket);
}
private ResponseHandler<String> responseHandler = new ResponseHandler<String>()
{
@Override
public String handleResponse(HttpResponse response)
throws ClientProtocolException, IOException
{
StatusLine statusLine = response.getStatusLine();
if (statusLine.getStatusCode() >= 300)
{
throw new HttpResponseException(statusLine.getStatusCode(),
statusLine.getReasonPhrase());
}
HttpEntity entity = response.getEntity();
if(entity == null)
return null;
InputStream instream = entity.getContent();
return this.toString(entity, instream, "UTF-8");
}
public String toString(
final HttpEntity entity,
final InputStream instream,
final String defaultCharset) throws IOException, ParseException
{
if (entity == null)
{
throw new IllegalArgumentException("HTTP entity may not be null");
}
if (instream == null)
{
return null;
}
if (entity.getContentLength() > Integer.MAX_VALUE)
{
throw new IllegalArgumentException("HTTP entity too large to be buffered in memory");
}
int i = (int)entity.getContentLength();
if (i < 0)
{
i = 4096;
}
String charset = EntityUtils.getContentCharSet(entity);
if (charset == null)
{
charset = defaultCharset;
}
if (charset == null)
{
charset = HTTP.DEFAULT_CONTENT_CHARSET;
}
Reader reader = new InputStreamReader(instream, charset);
StringBuilder buffer=new StringBuilder(i);
try
{
char[] tmp = new char[1024];
int l;
while((l = reader.read(tmp)) != -1)
{
buffer.append(tmp, 0, l);
}
} finally
{
reader.close();
}
return buffer.toString();
}
};
Run Code Online (Sandbox Code Playgroud)
}
nee*_*vek 24
听起来在完成处理响应后你不会使用实体.确保将以下代码放在finally块中:
if (httpEntity != null) {
try {
httpEntity.consumeContent();
} catch (IOException e) {
Log.e(TAG, "", e);
}
}
Run Code Online (Sandbox Code Playgroud)
我建议你阅读HttpClient教程.
Ric*_*ich 13
听起来很奇怪,但我遇到了同样的问题.我正在处理的应用程序是连续几次请求下载一堆缩略图以在ListView中显示,在第二个之后,它会挂起,好像HttpClient代码中有一个死锁.
我发现的奇怪修复是使用AndroidHttpClient而不是DefaultHttpClient.我一做到这一点,并且在走这条路线之前尝试了很多东西,它开始工作得很好.只需记住在完成请求后调用client.close().
AndroidHttpClient在文档中描述为DefaultHttpClient,具有"合理的默认设置和Android注册方案".由于这是在api level 8(Android 2.2)中引入的,我挖出源来复制这些"默认设置",这样我就可以比api级别更进一步使用它.这是我的复制默认值的代码和一个带有静态方法的辅助类,用于安全地关闭它
public class HttpClientProvider {
// Default connection and socket timeout of 60 seconds. Tweak to taste.
private static final int SOCKET_OPERATION_TIMEOUT = 60 * 1000;
public static DefaultHttpClient newInstance(String userAgent)
{
HttpParams params = new BasicHttpParams();
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
HttpProtocolParams.setContentCharset(params, HTTP.DEFAULT_CONTENT_CHARSET);
HttpProtocolParams.setUseExpectContinue(params, true);
HttpConnectionParams.setStaleCheckingEnabled(params, false);
HttpConnectionParams.setConnectionTimeout(params, SOCKET_OPERATION_TIMEOUT);
HttpConnectionParams.setSoTimeout(params, SOCKET_OPERATION_TIMEOUT);
HttpConnectionParams.setSocketBufferSize(params, 8192);
SchemeRegistry schReg = new SchemeRegistry();
schReg.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
schReg.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443));
ClientConnectionManager conMgr = new ThreadSafeClientConnManager(params, schReg);
DefaultHttpClient client = new DefaultHttpClient(conMgr, params);
return client;
}
}
Run Code Online (Sandbox Code Playgroud)
在另一堂课......
public static void safeClose(HttpClient client)
{
if(client != null && client.getConnectionManager() != null)
{
client.getConnectionManager().shutdown();
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
15012 次 |
| 最近记录: |