posts - 33,comments - 21,trackbacks - 0
          <2007年3月>
          25262728123
          45678910
          11121314151617
          18192021222324
          25262728293031
          1234567

          常用鏈接

          留言簿(4)

          隨筆分類(23)

          隨筆檔案(33)

          文章分類

          搜索

          •  

          最新評論

          閱讀排行榜

          評論排行榜

          一、“NetConnection”簡介:
          轉述Matrix上zhengyun_ustc所述:“你的HttpConnection是否封裝的足夠健壯呢?遇到各種情況,你是否有信心應對呢?譬如說,你要請求的Response包實在太大,以至于運營商給你掐了告訴你說超時;譬如說你是不是總要自己寫一個線程來專門作http連接?譬如說有一些移動運營商設置了caching proxy servers,妨礙了你的測試。”
          為了解決這個問題,一位日本程序員“JAY-F”針對MIDP1.0提供了一種robust的“NetConnection”封裝。這個HttpConnnection類負責管理連接并易于使用。
          二、“NetConnection”特性:
          1. 跨過Proxy-server阻礙:
          一些移動網絡放置了代理服務器用來提高訪問速度,但是它的cache也成為了開發人員測試/調試程序的一大障礙。“NetConnection”類使用一個簡單的http request屬性將server上的代理功能關閉掉。
          2. 使用線程分離的連接模式:
          本類可以使用單線程、多線程兩種模式運行,只要設置一個簡單的標志即可。
          3. 支持Http request range:
          由于服務商在其網絡上可能存在一些針對回應數據最大長度的限制,所以“NetConnection”類提供了構造request URL的功能使回應數據分為多個數據包。從而去除了前面的限制。
          三、netConnection是如何實現的?
          1。netConnection類結構分析:
          此類實現了Runnable接口,其運行模式支持多線程模式:當前只能由一個線程使用資源,其它線程wait。
          此類使用了一些靜態成員變量:

          				
          ????????//當前只能由一個線程使用singleton。
          ????????private static NetConnection singleton = new NetConnection();

          ????????private static HttpConnection httpConn;

          ????????private static String url;

          ????????private static String method;

          ????????private static byte[] data;
          ????????????????

          ????????private static String contentType;
          ????????

          ????????private static long lowRange;
          ????????

          ????????private static long highRange;
          ????????

          ????????private static boolean disableProxy;
          ????????

          ????????private static boolean detached;
          ????????
          ????????private static byte[] response;

          類方法:

          //線程run方法
          public void run()

          //當前運行的線程執行完畢后,通報給其它的由于等待資源而wait狀態的線程
          private synchronized void forceNotify()

          //當資源正在被其它線程使用時,當前線程進入wait狀態
          private synchronized void forceWait()

          //關閉http連接
          private static void severConnection()

          由于使用了這些static成員變量,所以一些操作方法需要同步(synchronized)。
          2。netConnection核心代碼解析:
          netConnection類的實現思想很簡單,就是設置一些request屬性和對于GET方法構造一個特殊的URL。更重要的是其作者對http協議的深入理解、嚴謹的代碼風格值得吾輩學習、研究。這也是本人分析其核心代碼的一大原因。

          /**
          * 實現了連接邏輯。
          * 調用者可以在分離的線程中使用netConnection類的靜態連接。
          * @throws IllegalStateException 如果此方法直接其它類調用則拋出該異常
          */
          public void run() {
          ????????
          ????????if (url == null) {
          ????????????????throw new IllegalStateException("Cannot invoke this method!");
          ????????}

          ????????
          ????????DataOutputStream dos = null;
          ????????DataInputStream dis = null;
          ????????StringBuffer buffer = null;

          ????????try {

          ????????????????int permissions = 0;
          ????????????????
          ????????????????//根據method值,設置Connector的權限(READ/READ_WRITE)
          ????????????????if (HttpConnection.GET.equals(method)) {
          ????????????????????????permissions = Connector.READ;
          ????????????????} else if (HttpConnection.POST.equals(method)) {
          ????????????????????????permissions = Connector.READ_WRITE;
          ????????????????}
          ????????????????
          ????????????????//如果關閉server代理功能,則構造noProxyUrl。
          ????????????????//原理:使用timestamp作為該URL中no-proxy參數值,
          ????????????????//????????致使server視其為client發來的新請求。
          ????????????????if (disableProxy) {
          ????????????????????????
          ????????????????????????boolean hasQueryParams = false;
          ????????????????????????
          ????????????????????????char[] ca = url.toCharArray();
          ????????????????????????//判斷原URL中是否含有參數
          ????????????????????????for (int loop = 0; loop < url.length(); loop++) {
          ????????????????????????????????
          ????????????????????????????????if (ca[loop] == '?') {
          ????????????????????????????????????????hasQueryParams = true;
          ????????????????????????????????????????break;
          ????????????????????????????????}
          ????????????????????????}
          ????????????????????????
          ????????????????????????//由于需要多次字符串拼接,所以使用可提供效率的StringBuffer類
          ????????????????????????StringBuffer noProxyUrl = new StringBuffer();

          ????????????????????????//將原URL內容復制到noProxyUrl
          ????????????????????????noProxyUrl.append(url);

          ????????????????????????//如果原URL中含有參數,
          ????????????????????????//??則需要在noProxyUrl中增加"&",
          ????????????????????????//??否則直接在noProxyUrl中增加"?",
          ????????????????????????//??這樣做為了后面增加no-proxy參數做準備。
          ????????????????????????if (hasQueryParams) {
          ????????????????????????????????noProxyUrl.append("&");
          ????????????????????????} else {
          ????????????????????????????????noProxyUrl.append("?");
          ????????????????????????}

          ????????????????????????//增加no-proxy參數
          ????????????????????????noProxyUrl.append("no-proxy=");
          ????????????????????????noProxyUrl.append(System.currentTimeMillis()); // timestamp
          ????????????????????????
          ????????????????????????//將構造好的noProxyUrl復制到原URL
          ????????????????????????url = noProxyUrl.toString();
          ????????????????}
          ????????????????
          ????????????????

          ????????????????// 打開Http 連接
          ????????????????httpConn = (HttpConnection) Connector.open(url, permissions, true);
          ????????????????//設置request方法
          ????????????????httpConn.setRequestMethod(method);

          ????????????????//如果request權限為READ(即request方法為GET),
          ????????????????//則需要設置http request屬性的Range。
          ????????????????//原理:設置http request屬性的Range后的,
          ????????????????//????????server接收到該request后將把response數據分成小部分發回。
          ????????????????//????????從而避免了部分運營商對http response size的限制。
          ????????????????if (permissions == Connector.READ) {????????
          ????????????????????????if (lowRange > -1 && lowRange < highRange) {
          ????????????????????????????????StringBuffer range = new StringBuffer();
          ????????????????????????????????
          ????????????????????????????????range.append("bytes=");
          ????????????????????????????????range.append(lowRange);
          ????????????????????????????????range.append("-");
          ????????????????????????????????range.append(highRange);
          ????????????????????????????????
          ????????????????????????????????httpConn.setRequestProperty("Range", range.toString());
          ????????????????????????}
          ????????????????//否則,request權限為READ_WRITE(即request方法為POST),
          ????????????????//那么設置request的Content-Type屬性。
          ????????????????} else if (permissions == Connector.READ_WRITE) {
          ????????????????????????// POST request
          ????????????????????????httpConn.setRequestProperty("Content-Type", contentType);
          ????????????????????????dos = httpConn.openDataOutputStream();
          ????????????????????????dos.write(data);
          ????????????????}
          ????????
          ????????} catch (Exception e) {
          ????????
          ????????????????exceptionPipe = e;
          ????????????????//如果程序運行在多線程模式,則在異常發生后需要喚醒其它睡眠的線程繼續run
          ????????????????if (detached) {
          ????????????????????????forceNotify();
          ????????????????}
          ????????????????
          ????????????????return;
          ????????????????
          ????????} finally {

          ????????????????try {
          ????????????????????????try {
          ????????????????????????????????if (dos != null) {
          ????????????????????????????????????????// 關閉dos
          ????????????????????????????????????????dos.close();
          ????????????????????????????????}
          ????????????????????????} catch (Exception e) {
          ????????????????????????????????// 如果程序運行在多線程模式,則在異常發生后需要喚醒其它睡眠的線程繼續run
          ????????????????????????????????if (exceptionPipe == null) {
          ????????????????????????????????????????exceptionPipe = e;
          ????????????????????????????????????????
          ????????????????????????????????????????if (detached) {
          ????????????????????????????????????????????????forceNotify();
          ????????????????????????????????????????}
          ????????????????????????????????????????return;
          ????????????????????????????????}
          ????????????????????????} finally {
          ????????????????????????????????dos = null;
          ????????????????????????}
          ????????????????????????
          ????????????????????????// 讀取http連接的回應代碼
          ????????????????????????int responseCode = httpConn.getResponseCode();
          ????????????????????????
          ????????????????????????//當request方法為GET,并設置了request range時,接收到的回應代碼為HTTP_PARTIAL
          ????????????????????????//當request方法為POST,接收到的回應代碼為HTTP_OK
          ????????????????????????//如果上述兩種回應代碼均沒有收到,則表明連接失敗或者出問題
          ????????????????????????if (responseCode != HttpConnection.HTTP_OK
          ????????????????????????????????????????&& responseCode != HttpConnection.HTTP_PARTIAL) {

          ????????????????????????????????if (exceptionPipe == null) {
          ????????????????????????????????????????StringBuffer errorCode = new StringBuffer();
          ????????????????????????????????????????errorCode.append("Response code from server: ");
          ????????????????????????????????????????errorCode.append(responseCode);
          ????????????????????????????????????????errorCode.append("\nMessage: [");
          ????????????????????????????????????????errorCode.append(httpConn.getResponseMessage());
          ????????????????????????????????????????errorCode.append("]");
          ????????????????????????????????????????
          ????????????????????????????????????????exceptionPipe = new IOException(errorCode.toString());
          ????????????????????????????????????????
          ????????????????????????????????????????if (detached) {
          ????????????????????????????????????????????????forceNotify();
          ????????????????????????????????????????}
          ????????????????????????????????????????return;
          ????????????????????????????????}
          ????????????????????????}

          ????????????????????????//如果收到了上述的兩種回應代碼之一,則可以繼續讀取server的response數據
          ????????????????????????dis = httpConn.openDataInputStream();

          ????????????????????????//循環讀取repsonse數據
          ????????????????????????int ch;
          ????????????????????????buffer = new StringBuffer();
          ????????????????while ((ch = dis.read()) != -1) {
          ????????????????????????buffer.append((char) ch);
          ????????????????}

          ????????????????//將response數據進行必要的編碼轉換????????????????
          ????????????????????????response = buffer.toString().getBytes("ISO8859_1");
          ????????????????????????//接收到回應后,表明整個http會話過程結束,線程將結束。
          ????????????????????????//如果程序運行在多線程模式,則此時需要喚醒其它睡眠的線程繼續run
          ????????????????????????if (detached) {
          ????????????????????????????????forceNotify();
          ????????????????????????}
          ????????????????????????
          ????????????????????????return;

          ????????????????} catch (Exception e) {
          ????????????????????????
          ????????????????????????if (exceptionPipe == null) {
          ????????????????????????????????exceptionPipe = e;
          ????????????????????????????????
          ????????????????????????????????if (detached) {
          ????????????????????????????????????????forceNotify();
          ????????????????????????????????}
          ????????????????????????????????
          ????????????????????????????????return;
          ????????????????????????}
          ????????????????} finally {
          ????????????????????
          ????????????????????????try {
          ????????????????????????????????if (dis != null) {
          ????????????????????????????????????????// 關閉dis
          ????????????????????????????????????????dis.close();
          ????????????????????????????????}
          ????????????????????????} catch (Exception e) {
          ????????????????????????????????// 若關閉dis時發生異常,則進行異常處理
          ????????????????????????????????if (exceptionPipe == null) {
          ????????????????????????????????????????exceptionPipe = e;
          ????????????????????????????????????????
          ????????????????????????????????????????if (detached) {
          ????????????????????????????????????????????????forceNotify();
          ????????????????????????????????????????}
          ????????????????????????????????????????return;
          ????????????????????????????????}
          ????????????????????????} finally {
          ????????????????????????????????dis = null;
          ????????????????????????}
          ????????????????????????
          ????????????????????????try {
          ????????????????????????????????if (httpConn != null) {
          ????????????????????????????????????????//關閉http連接
          ????????????????????????????????????????httpConn.close();

          ????????????????????????????????????????httpConn = null;
          ????????????????????????????????}
          ????????????????????????} catch (Exception e) {

          ????????????????????????????????if (exceptionPipe == null) {
          ????????????????????????????????????????exceptionPipe = e;
          ????????????????????????????????????????
          ????????????????????????????????????????if (detached) {
          ????????????????????????????????????????????????forceNotify();
          ????????????????????????????????????????}
          ????????????????????????????????????????return;
          ????????????????????????????????}
          ????????????????????????}
          ????????????????}
          ????????}
          }

          五、參考資料:
          聯系netConnection作者:JAY-F
          源代碼下載
          HTTP/1.1定義
          posted on 2007-03-17 18:00 英明 閱讀(1249) 評論(0)  編輯  收藏 所屬分類: J2ME
          主站蜘蛛池模板: 上高县| 长治市| 云阳县| 抚松县| 灵丘县| 北票市| 邵东县| 门头沟区| 凤台县| 衡东县| 衡阳县| 宣恩县| 田阳县| 三穗县| 蕉岭县| 重庆市| 丹江口市| 噶尔县| 郁南县| 嘉鱼县| 光泽县| 榆树市| 西宁市| 永川市| 湘潭县| 同心县| 县级市| 运城市| 石阡县| 定兴县| 栾川县| 乌海市| 社旗县| 施甸县| 榆社县| 南平市| 高州市| 文化| 安平县| 晋中市| 巴马|