標籤:android c style class blog code
Android通過HttpConnectionParams類為http參數設定提供了兩個逾時的設定選項,分別是setSoTimeout和setConnectionTimeout。初看一眼Android官方給的文檔對這個兩個方法的具體含義有一種不理解不夠清楚的感覺,所以決定通過測試的方式來看看到底在什麼情況下這兩個參數會起作用。
經過測試可以發現,setConnectionTimeout設定了建立串連的逾時,這是針對TCP的三向交握而言的,如果在指定時間內無法和http伺服器建立TCP串連,就會拋出ConnectionTimeoutException。setSoTimeout則設定的是TCP保活時間,在建立了串連之後的指定時間內沒有收到伺服器發來的相應的資料包,則拋出SocketTimeoutException.
一、測試代碼
private String urlString; private int timeout1,timeout2; MyAsyncTask(String url,int timeout1,int timeout2){ urlString=url; this.timeout1=timeout1; this.timeout2=timeout2; } @Override protected String doInBackground(String... params) { httpget(urlString,timeout1,timeout2); return "test"; } protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); new MyAsyncTask("http://www.xiaonei.com:1234",3000,5000).execute("start"); new MyAsyncTask("http://www.baidu.com",3000,5000).execute("start"); } private void httpget(String Url,int timeout1,int timeout2) { Log.v("httpget", "httpget start timeout1 is "+timeout1+"timeout2 is "+timeout2); int timeoutConnection = timeout1; // until connection is established int timeoutSocket = timeout2; // timeout for waiting for data HttpParams httpParameters = new BasicHttpParams(); HttpConnectionParams.setConnectionTimeout(httpParameters, timeoutConnection); HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket); DefaultHttpClient httpClient = new DefaultHttpClient(httpParameters); HttpGet postRequest = new HttpGet(Url); HttpResponse httpResp = null; try { httpResp = httpClient.execute(postRequest); } catch (ClientProtocolException e) { Log.v("Main", "clinet protocol exception"); return; }catch (SocketTimeoutException e) { // TODO: handle exception Log.v("Main", "socket timeout"+timeout2); return; }catch (ConnectTimeoutException e) { // TODO: handle exception Log.v("Main", "connection timeout"+timeout1); return; } catch (IOException e) { Log.v("Main", "io exception"); return; } }
二、setConnectionTimeout測試
在httpget的url中寫入一個無法進行通訊的地址如“10.1.1.1”或者是一個公開伺服器沒有開放的連接埠號碼如“www.xiaonei.com:1234”都會出現ConnnectionTimeoutException.對於一個無法通訊的IP地址,Android系統直接構造一個發送至改地址的TCP建立串連資料包,不過由於該地址不存在,所以不會收到確認,到了設定好的逾時時間就發生逾時事件。對於不存在連接埠號碼的情況基本類似。
三、setSoTimeout測試
setSoTimeout設定了socket的保活逾時時間。這裡的測試方法是通過給Android終端設定代理,在代理收到了Android終端發來的http請求之後,直接截獲http請求不予發送,到了逾時時間拋出socketTimeoutException.這樣一種http資料包截獲的方式可以通過fiddler方便地實現。利用fiddler代理功能進行Androidhttp抓包配置方法見http://www.oschina.net/question/221817_129716,fiddler攔截資料包的方法見http://www.mzwu.com/article.asp?id=3509。
配置了fiddler代理並對http包進行攔截之後,運行測試程式可以得到如下輸出。兩個http請求都輸出了socket timeout。第一個請求之所以也輸出了socket timeout,是因為Android終端和代理之間能夠正常建立串連,所以不會出現connection timeout,但是代理轉交了Android終端發來的http請求之後無法獲得響應,也就無法將相應的資訊反饋給用戶端,用戶端出現了socket timeout。
四、AsyncTask的進一步理解
從以上測試結果中可以看出,雖然在oncreate函數中同時調用了AsyncTask類分別發送兩個不同的http請求,但是第二個被調用的Asyntask需要等到第一個被調用的逾時之後才能被執行。這是因為Android在3.0之後,AsyncTask的實現上將所有的Asynctask都放到了一個線程中,按照一定的順序有先後的執行。更詳細的分析可以參考http://blog.csdn.net/singwhatiwanna/article/details/17596225。
五、參考材料
[1]關於http逾時參數的解釋:http://stackoverflow.com/a/18185568/1767800
[2]關於如何得到http連線逾時:http://stackoverflow.com/questions/100841/artificially-create-a-connection-timeout-error