正文  网络通信 > HTTP >

Android·HTTP超时机制

由于手机端应用的响应,与当时的无线通信网络状况有很大的关联。而通信网络往往具有不稳定,延迟长的特点。所以,在我们的应用程序中,当我们请求网络的时候,超时机制的应用就显得特别重要。超时机制主要有:1、......

由于手机端应用的响应,与当时的无线通信网络状况有很大的关联。而通信网络往往具有不稳定,延迟长的特点。所以,在我们的应用程序中,当我们请求网络的时候,超时机制的应用就显得特别重要。

超时机制主要有:

1、HTTP请求超时机制

2、Socket通信超时机制

HTTP请求超时机制

01 public static void main(String[] args){
02  
03 long a=System.currentTimeMillis();
04 try{
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″));
10 String inputLine;
11  
12 while ((inputLine = in.readLine()) != null){
13 System.out.println(inputLine);
14 in.close();
15 System.out.println(System.currentTimeMillis()-a);
16 }
17 } catch (MalformedURLException e) {
18 e.printStackTrace();
19 } catch (UnsupportedEncodingException e) {
20 e.printStackTrace();
21 } catch (IOException e) {
22 e.printStackTrace();
23 }
24  
25 }

 

如果超时将抛出以下异常 
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还行,用在项目中还是不够完善。自己写了一个例子,有不完善之处,欢迎大家指正。

需要注意的地方:有三个方面

  1. 如何控制超时机制
  2. 如何处理异常
  3. 如何处理请求错误的 

 

01 private class XmlAsyncLoader extends XmlResourceRequest {
02  
03  private boolean mIsCancle = false;
04  private HttpGet mGet;
05  private HttpClient mHttp;
06  
07  public XmlAsyncLoader(MxActivity<?> activity, String url)
08  throws MalformedURLException {
09  super(activity, url);
10  }
11  
12  @Override
13  protected void doTaskInBackground() {
14  // 请求数据
15  if (mUrl.toLowerCase().startsWith("http://")) {
16  mGet = initHttpGet(mUrl);
17  mHttp = initHttp();
18  try {
19  HttpResponse response = mHttp.execute(mGet);
20  if (mIsCancle) {
21  return;
22  }
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());
27  return;
28  }
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
36  onFoundNoItems();
37  return;
38  }
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);
43  if (mIsCancle){
44  return;
45  }
46  onFoundItem(info, 80 + 20 * (i + 1) / len);
47  addUrlToQueue(info.userIconUrl);
48  }
49  };
50  
51  }
52  }catch(ConnectTimeoutException e){
53  onResponseError("time out");
54  } catch (ClientProtocolException e) {
55  --mCurrentPage;
56  e.printStackTrace();
57  } catch (IOException e) {
58  --mCurrentPage;
59  e.printStackTrace();
60  } catch (XmlPullParserException e) {
61  --mCurrentPage;
62  e.printStackTrace();
63  }finally{
64  notifyLoadFinish();
65  notifyLoadImages();
66  mHttp.getConnectionManager().shutdown();
67  }
68  
69  }
70  }
71  
72  
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);// 连接超时
79  return client;
80  }
81  
82  private HttpGet initHttpGet(String mUrl) {
83  HttpGet get = new HttpGet(mUrl);
84  initHeader(get);
85  return get;
86  }
87  
88  
89  @Override
90  public boolean tryCancel() {
91  Log.i(TAG, "tryCanle is working");
92  mGet.abort();
93  mIsCancle = true;
94  mHttp.getConnectionManager().shutdown();
95  notifyLoadFinish();
96  return true;
97  }
98  
99  }

 

这是一个异步任务类,发送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关键字

不管是请求成功,还是失败,都需要关闭链接。