如何设置HttpResponse超时为Android在Java

我创建了以下函数来检查连接状态:

private void checkConnectionStatus() {
HttpClient httpClient = new DefaultHttpClient();


try {
String url = "http://xxx.xxx.xxx.xxx:8000/GaitLink/"
+ strSessionString + "/ConnectionStatus";
Log.d("phobos", "performing get " + url);
HttpGet method = new HttpGet(new URI(url));
HttpResponse response = httpClient.execute(method);


if (response != null) {
String result = getResponse(response.getEntity());
...

当我关闭服务器测试执行等待很长时间在行

HttpResponse response = httpClient.execute(method);

有人知道如何设置超时以避免等待太长时间吗?

谢谢!

203699 次浏览

如果你正在使用Jakarta的HTTP客户端库,那么你可以这样做:

        HttpClient client = new HttpClient();
client.getParams().setParameter(HttpClientParams.CONNECTION_MANAGER_TIMEOUT, new Long(5000));
client.getParams().setParameter(HttpClientParams.SO_TIMEOUT, new Integer(5000));
GetMethod method = new GetMethod("http://www.yoururl.com");
method.getParams().setParameter(HttpMethodParams.SO_TIMEOUT, new Integer(5000));
method.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,
int statuscode = client.executeMethod(method);

在我的示例中,设置了两个超时。连接超时抛出java.net.SocketTimeoutException: Socket is not connected,套接字超时抛出java.net.SocketTimeoutException: The operation timed out

HttpGet httpGet = new HttpGet(url);
HttpParams httpParameters = new BasicHttpParams();
// Set the timeout in milliseconds until a connection is established.
// The default value is zero, that means the timeout is not used.
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 = 5000;
HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket);


DefaultHttpClient httpClient = new DefaultHttpClient(httpParameters);
HttpResponse response = httpClient.execute(httpGet);

如果你想设置任何现有HTTPClient(例如DefaultHttpClient或AndroidHttpClient)的参数,你可以使用setparam ()函数。

httpClient.setParams(httpParameters);

在客户端进行设置。

AndroidHttpClient client = AndroidHttpClient.newInstance("Awesome User Agent V/1.0");
HttpConnectionParams.setConnectionTimeout(client.getParams(), 3000);
HttpConnectionParams.setSoTimeout(client.getParams(), 5000);

我已经在JellyBean上成功地使用了这一点,但也应该适用于较旧的平台....

HTH

HttpParams httpParameters = new BasicHttpParams();
HttpProtocolParams.setVersion(httpParameters, HttpVersion.HTTP_1_1);
HttpProtocolParams.setContentCharset(httpParameters,
HTTP.DEFAULT_CONTENT_CHARSET);
HttpProtocolParams.setUseExpectContinue(httpParameters, true);


// Set the timeout in milliseconds until a connection is
// established.
// The default value is zero, that means the timeout is not used.
int timeoutConnection = 35 * 1000;
HttpConnectionParams.setConnectionTimeout(httpParameters,
timeoutConnection);
// Set the default socket timeout (SO_TIMEOUT)
// in milliseconds which is the timeout for waiting for data.
int timeoutSocket = 30 * 1000;
HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket);

如果你正在使用HttpURLConnection,调用setConnectTimeout(),如在这里所述:

URL url = new URL(myurl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(CONNECT_TIMEOUT);

你可以通过HttpClient -android-4.3.5创建HttpClient实例,它可以很好地工作。

 SSLContext sslContext = SSLContexts.createSystemDefault();
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
sslContext,
SSLConnectionSocketFactory.STRICT_HOSTNAME_VERIFIER);
RequestConfig.Builder requestConfigBuilder = RequestConfig.custom().setCircularRedirectsAllowed(false).setConnectionRequestTimeout(30*1000).setConnectTimeout(30 * 1000).setMaxRedirects(10).setSocketTimeout(60 * 1000);
CloseableHttpClient hc = HttpClients.custom().setSSLSocketFactory(sslsf).setDefaultRequestConfig(requestConfigBuilder.build()).build();

如果你正在使用默认的http客户端,下面是如何使用默认的http参数:

HttpClient client = new DefaultHttpClient();
HttpParams params = client.getParams();
HttpConnectionParams.setConnectionTimeout(params, 3000);
HttpConnectionParams.setSoTimeout(params, 3000);

原始信用归http://www.jayway.com/2009/03/17/configuring-timeout-with-apache-httpclient-40/

对于那些说@kuester2000的答案不起作用的人,请注意HTTP请求,首先尝试找到带有DNS请求的主机IP,然后向服务器发出实际的HTTP请求,因此您可能还需要为DNS请求设置超时。

如果你的代码没有超时的DNS请求,这是因为你能够到达DNS服务器或你正在击中Android DNS缓存。顺便说一下,您可以通过重新启动设备来清除这个缓存。

这段代码扩展了原始的答案,包括一个自定义超时的手动DNS查找:

//Our objective
String sURL = "http://www.google.com/";
int DNSTimeout = 1000;
int HTTPTimeout = 2000;


//Get the IP of the Host
URL url= null;
try {
url = ResolveHostIP(sURL,DNSTimeout);
} catch (MalformedURLException e) {
Log.d("INFO",e.getMessage());
}


if(url==null){
//the DNS lookup timed out or failed.
}


//Build the request parameters
HttpParams params = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(params, HTTPTimeout);
HttpConnectionParams.setSoTimeout(params, HTTPTimeout);


DefaultHttpClient client = new DefaultHttpClient(params);


HttpResponse httpResponse;
String text;
try {
//Execute the request (here it blocks the execution until finished or a timeout)
httpResponse = client.execute(new HttpGet(url.toString()));
} catch (IOException e) {
//If you hit this probably the connection timed out
Log.d("INFO",e.getMessage());
}


//If you get here everything went OK so check response code, body or whatever

使用方法:

//Run the DNS lookup manually to be able to time it out.
public static URL ResolveHostIP (String sURL, int timeout) throws MalformedURLException {
URL url= new URL(sURL);
//Resolve the host IP on a new thread
DNSResolver dnsRes = new DNSResolver(url.getHost());
Thread t = new Thread(dnsRes);
t.start();
//Join the thread for some time
try {
t.join(timeout);
} catch (InterruptedException e) {
Log.d("DEBUG", "DNS lookup interrupted");
return null;
}


//get the IP of the host
InetAddress inetAddr = dnsRes.get();
if(inetAddr==null) {
Log.d("DEBUG", "DNS timed out.");
return null;
}


//rebuild the URL with the IP and return it
Log.d("DEBUG", "DNS solved.");
return new URL(url.getProtocol(),inetAddr.getHostAddress(),url.getPort(),url.getFile());
}

这个类来自这篇博文。如果你要用的话,去看看注释。

public static class DNSResolver implements Runnable {
private String domain;
private InetAddress inetAddr;


public DNSResolver(String domain) {
this.domain = domain;
}


public void run() {
try {
InetAddress addr = InetAddress.getByName(domain);
set(addr);
} catch (UnknownHostException e) {
}
}


public synchronized void set(InetAddress inetAddr) {
this.inetAddr = inetAddr;
}
public synchronized InetAddress get() {
return inetAddr;
}
}

一种选择是从Square使用OkHttp客户端。

添加库依赖项

在构建中。Gradle,包括这一行:

compile 'com.squareup.okhttp:okhttp:x.x.x'

其中x.x.x是所需的库版本。

设置客户端

例如,如果你想设置一个60秒的超时,这样做:

final OkHttpClient okHttpClient = new OkHttpClient();
okHttpClient.setReadTimeout(60, TimeUnit.SECONDS);
okHttpClient.setConnectTimeout(60, TimeUnit.SECONDS);

ps:如果你的minSdkVersion大于8,你可以使用TimeUnit.MINUTES。所以,你可以简单地使用:

okHttpClient.setReadTimeout(1, TimeUnit.MINUTES);
okHttpClient.setConnectTimeout(1, TimeUnit.MINUTES);

有关单元的更多详细信息,请参见TimeUnit

public boolean isInternetWorking(){
try {
int timeOut = 5000;
Socket socket = new Socket();
SocketAddress socketAddress = new InetSocketAddress("8.8.8.8",53);
socket.connect(socketAddress,timeOut);
socket.close();
return true;
} catch (IOException e) {
//silent
}
return false;
}