我正在编写一个连接到Web服务的应用程序,如果它无法建立连接,我不希望它等待太久。因此,我设置了httpparams的connectionTimeout。但它似乎没有任何影响。
测试我暂时关闭WLAN。应用程序尝试连接相当长的时间(超过我想要的3秒),然后抛出UnknownHostException。
这是我的代码:
try{
HttpClient httpclient = new DefaultHttpClient();
HttpParams params = httpclient.getParams();
HttpConnectionParams.setConnectionTimeout(params, 3000);
HttpConnectionParams.setSoTimeout(params, 3000);
httppost = new HttpPost(URL);
StringEntity se = new StringEntity(envelope,HTTP.UTF_8);
httppost.setEntity(se);
//Code stops here until UnknownHostException is thrown.
BasicHttpResponse httpResponse = (BasicHttpResponse) httpclient.execute(httppost);
HttpEntity entity = httpResponse.getEntity();
return entity;
}catch (Exception e){
e.printStackTrace();
}
任何人都有我错过的想法吗?
答案 0 :(得分:74)
尝试这样做:
HttpPost httpPost = new HttpPost(url);
StringEntity se = new StringEntity(envelope,HTTP.UTF_8);
httpPost.setEntity(se);
HttpParams httpParameters = new BasicHttpParams();
// Set the timeout in milliseconds until a connection is established.
int timeoutConnection = 3000;
HttpConnectionParams.setConnectionTimeout(httpParameters, timeoutConnection);
// Set the default socket timeout (SO_TIMEOUT)
// in milliseconds which is the timeout for waiting for data.
int timeoutSocket = 3000;
HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket);
DefaultHttpClient httpClient = new DefaultHttpClient(httpParameters);
BasicHttpResponse httpResponse = (BasicHttpResponse) httpClient.execute(httpPost);
HttpEntity entity = httpResponse.getEntity();
return entity;
然后您可以捕获可能的ConnectTimeoutException
。
答案 1 :(得分:9)
使用标记的解决方案,我在30秒后仍然会收到UnknownHostException。在这种情况下,设备连接到wifi路由器,但没有互联网访问。
采取的方法是启动一个只会尝试解析主机名的AsyncTask。阻塞调用每隔250毫秒检查一次是否成功,4秒后它将取消该任务并返回。
这就是我解决它的方法:
private boolean dnsOkay = false;
private static final int DNS_SLEEP_WAIT = 250;
private synchronized boolean resolveDns(){
RemoteDnsCheck check = new RemoteDnsCheck();
check.execute();
try {
int timeSlept = 0;
while(!dnsOkay && timeSlept<4000){
//Log.d("RemoteDnsCheck", "sleeping");
Thread.sleep(DNS_SLEEP_WAIT);
timeSlept+=DNS_SLEEP_WAIT;
//Log.d("RemoteDnsCheck", "slept");
}
} catch (InterruptedException e) {
}
if(!dnsOkay){
Log.d("resolveDns", "cancelling");
check.cancel(true);
Log.d("resolveDns", "cancelled");
}
return dnsOkay;
}
private class RemoteDnsCheck extends AsyncTask<Void, Void, Void>{
@Override
protected Void doInBackground(Void... params) {
try {
Log.d("RemoteDnsCheck", "starting");
dnsOkay = false;
InetAddress addr = InetAddress.getByName(baseServiceURL);
if(addr!=null){
Log.d("RemoteDnsCheck", "got addr");
dnsOkay = true;
}
} catch (UnknownHostException e) {
Log.d("RemoteDnsCheck", "UnknownHostException");
}
return null;
}
}
然后,无论何时我想进行网络通话,都会在功能开始时调用:
if(!resolveDns()){
return null;
}
答案 2 :(得分:3)
请参阅:https://stackoverflow.com/a/20031077/2609238
问题可能出在Apache HTTP Client中。请参阅HTTPCLIENT-1098。已在4.1.2中修复。
超时异常会尝试将DNS反转为IP,以便进行日志记录。这需要额外的时间,直到实际触发异常。
答案 3 :(得分:1)
这种方法对我有用:
AndroidHttpTransport androidHttpTransport = new AndroidHttpTransport( endpoint, 3000) ;
答案 4 :(得分:0)
HttpConnectionParams.setConnectionTimeout(httpParameters, timeoutConnection);
// Set the default socket timeout (SO_TIMEOUT)