由于手机端应用的响应,与当时的无线通信网络状况有很大的关联。而通信网络往往具有不稳定,延迟长的特点。所以,在我们的应用程序中,当我们请求网络的时候,超时机制的应用就显得特别重要。
超时机制主要有:
1、HTTP请求超时机制
2、Socket通信超时机制
HTTP请求超时机制
01 |
public static void main(String[] args){ |
03 |
long a=System.currentTimeMillis(); |
05 |
URL myurl = new URL(“http://www.oschina.cn/”); |
06 |
URLConnection myurlcon = myurl.openConnection(); |
07 |
myurlcon.setConnectTimeout(1000); |
08 |
myurlcon.setReadTimeout(1000); |
09 |
BufferedReader in = new BufferedReader(newInputStreamReader(myurlcon.getInputStream(),”UTF-8″)); |
12 |
while ((inputLine = in.readLine()) != null){ |
13 |
System.out.println(inputLine); |
15 |
System.out.println(System.currentTimeMillis()-a); |
17 |
} catch (MalformedURLException e) { |
19 |
} catch (UnsupportedEncodingException e) { |
21 |
} catch (IOException e) { |
如果超时将抛出以下异常
01 |
java.net.SocketTimeoutException: Read timed out |
02 |
at java.net.SocketInputStream.socketRead0(Native Method) |
03 |
at java.net.SocketInputStream.read(SocketInputStream.java:129) |
04 |
at java.io.BufferedInputStream.fill(BufferedInputStream.java:218) |
05 |
at java.io.BufferedInputStream.read1(BufferedInputStream.java:256) |
06 |
at java.io.BufferedInputStream.read(BufferedInputStream.java:313) |
07 |
at sun.net.www.http.HttpClient.parseHTTPHeader(HttpClient.java:606) |
08 |
at sun.net.www.http.HttpClient.parseHTTP(HttpClient.java:554) |
09 |
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:940) |
10 |
at com.Test.main(Test.java:52) |
补充内容:
在android项目中,如果有用到http请求,就必须也应该加上http请求的超时管理,异常管理,项目中遇到这个需求,google上搜索到了一大堆,但是写的都比较简单,做个demo还行,用在项目中还是不够完善。自己写了一个例子,有不完善之处,欢迎大家指正。
需要注意的地方:有三个方面
- 如何控制超时机制
- 如何处理异常
- 如何处理请求错误的
01 |
private class XmlAsyncLoader extends XmlResourceRequest { |
03 |
private boolean mIsCancle = false; |
05 |
private HttpClient mHttp; |
07 |
public XmlAsyncLoader(MxActivity<?> activity, String url) |
08 |
throws MalformedURLException { |
13 |
protected void doTaskInBackground() { |
15 |
if (mUrl.toLowerCase().startsWith("http://")) { |
16 |
mGet = initHttpGet(mUrl); |
19 |
HttpResponse response = mHttp.execute(mGet); |
23 |
if (response != null) { |
24 |
if(response.getStatusLine().getStatusCode()!=HttpStatus.SC_OK){ |
25 |
onResponseError("network error"); |
26 |
Log.v(TAG, "the code is :"+response.getStatusLine().getStatusCode()); |
29 |
notifyUpdateProgress(70); |
30 |
Document doc = getDocumet(response); |
31 |
Element root = doc.getDocumentElement(); |
32 |
NodeList appList = root |
33 |
.getElementsByTagName(Item_ELEMENT_NAME); |
34 |
final int len = appList.getLength(); |
35 |
if (len <= 0) {// 没有items |
39 |
for (int i = 0; i < len; i++) { |
40 |
Element item = (Element) appList.item(i); |
41 |
if (item.getNodeType() == Node.ELEMENT_NODE) { |
42 |
HahaItemInfo info = createHahaItemIno(item); |
46 |
onFoundItem(info, 80 + 20 * (i + 1) / len); |
47 |
addUrlToQueue(info.userIconUrl); |
52 |
}catch(ConnectTimeoutException e){ |
53 |
onResponseError("time out"); |
54 |
} catch (ClientProtocolException e) { |
57 |
} catch (IOException e) { |
60 |
} catch (XmlPullParserException e) { |
66 |
mHttp.getConnectionManager().shutdown(); |
73 |
private HttpClient initHttp() { |
74 |
HttpClient client = new DefaultHttpClient(); |
75 |
client.getParams().setIntParameter( |
76 |
HttpConnectionParams.SO_TIMEOUT, TIME_OUT_DELAY); // 超时设置 |
77 |
client.getParams().setIntParameter( |
78 |
HttpConnectionParams.CONNECTION_TIMEOUT, TIME_OUT_DELAY);// 连接超时 |
82 |
private HttpGet initHttpGet(String mUrl) { |
83 |
HttpGet get = new HttpGet(mUrl); |
90 |
public boolean tryCancel() { |
91 |
Log.i(TAG, "tryCanle is working"); |
94 |
mHttp.getConnectionManager().shutdown(); |
这是一个异步任务类,发送get请求请求数据,解析服务器的响应数据,同时通知ui线程更新ui
在android中,互联网交互的写法有很多,可以使用apache提供的包,也可以使用google提供的api,我不知道那种更好,只是习惯于使用
apache的api。
1. 设置超时机制
client.getParams().setIntParameter( HttpConnectionParams.SO_TIMEOUT, TIME_OUT_DELAY); // 超时设置 client.getParams().setIntParameter( HttpConnectionParams.CONNECTION_TIMEOUT, TIME_OUT_DELAY);// 连接超时
这里设置了两种超时,第一种是请求超时,第二种时连接超时。
当向服务器发出请求后,请求和服务器建立socket连接,但是很长时间内都没有建立socket连接,这就时第一种请求超时,这种情况主要发生在请求了
一个不存在的服务器。超时之后,会抛出InterruptedIOException异常。
Timeout for blocking operations. The argument value is specified in
milliseconds. An InterruptedIOException is thrown if this timeout
expires.
客户端已经与服务器建立了socket连接,但是服务器并没有处理客户端的请求,没有相应服务器,这就是第二种连接超时。这中超时会抛出
ConnectTimeoutException异常,ConnectTimeoutException继承自InterruptedIOException,所以只要捕获ConnectTimeoutException
就可以了。
2. 分析一下请求的过程
2.1 HttpResponse response = mHttp.execute(mGet);
执行请求方法,获取服务器响应,(这里有个不太成熟的看法,response不可能为null,还有待验证)。
2.2 获取请求响应码
if(response.getStatusLine().getStatusCode()!=HttpStatus.SC_OK){ onResponseError("network error"); Log.v(TAG, "the code is :"+response.getStatusLine().getStatusCode()); return; }
即使连接上服务器,并且从服务器上获取了数据,也有可能时服务器返回的错误信息,因此也需要特殊处理。
2.3 异常处理
对于异常,不能简单的捕获就完事,例如上面的代码中,我请求第三页的数据,如果发生异常,请求不成功,那么我就需要让当前页数回滚,
如果成功了就不用回滚了,所以需要对异常进行处理
2.4 finally关键字
不管是请求成功,还是失败,都需要关闭链接。