<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    讓變化成為計劃的一部分

    歡迎大家探討本Blog涉及的所有軟件課題。我的Google Talk ID:zhengyun(at)gmail.com。

    我最希望軟件帶給用戶的感受是:美好的體驗、舒適感、簡約、干凈...

    posts - 32, comments - 8, trackbacks - 0, articles - 0
      BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

    另外,還有一篇必讀的文章《Debugging MIDP HTTP Requests,http://developers.sun.com/techtopics/mobility/midp/articles/httpdebug/》,也給出了一份源代碼,http://developers.sun.com/techtopics/mobility/midp/articles/httpdebug/src/httpwrapper.zip,算是另外一種封裝實現(xiàn)了。

    一個來自日本的MIDP 1.0 HttpConnection類的robust封裝

    作者:zhengyun_ustc、cleverpig



    一、“NetConnection”簡介:

    轉(zhuǎn)述Matrix上zhengyun_ustc所述:“你的HttpConnection是否封裝的足夠健壯呢?遇到各種情況,你是否有信心應(yīng)對呢?譬如說,你要請求的Response包實在太大,以至于運營商給你掐了告訴你說超時;譬如說你是不是總要自己寫一個線程來專門作http連接?譬如說有一些移動運營商設(shè)置了caching proxy servers,妨礙了你的測試。”

    為了解決這個問題,一位日本程序員“JAY-F”針對MIDP1.0提供了一種robust的“NetConnection”封裝。這個HttpConnnection類負(fù)責(zé)管理連接并易于使用。

    二、“NetConnection”特性:

    1. 跨過Proxy-server阻礙:

    一些移動網(wǎng)絡(luò)放置了代理服務(wù)器用來提高訪問速度,但是它的cache也成為了開發(fā)人員測試/調(diào)試程序的一大障礙。“NetConnection”類使用一個簡單的http request屬性將server上的代理功能關(guān)閉掉。

    2. 使用線程分離的連接模式:

    本類可以使用單線程、多線程兩種模式運行,只要設(shè)置一個簡單的標(biāo)志即可。

    3. 支持Http request range:

    由于服務(wù)商在其網(wǎng)絡(luò)上可能存在一些針對回應(yīng)數(shù)據(jù)最大長度的限制,所以“NetConnection”類提供了構(gòu)造request URL的功能使回應(yīng)數(shù)據(jù)分為多個數(shù)據(jù)包。從而去除了前面的限制。

    三、netConnection是如何實現(xiàn)的?

    1。netConnection類結(jié)構(gòu)分析:

    此類實現(xiàn)了Runnable接口,其運行模式支持多線程模式:當(dāng)前只能由一個線程使用資源,其它線程wait。

    此類使用了一些靜態(tài)成員變量:

            //當(dāng)前只能由一個線程使用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()

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

    //當(dāng)資源正在被其它線程使用時,當(dāng)前線程進(jìn)入wait狀態(tài)
    private synchronized void forceWait()

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


    由于使用了這些static成員變量,所以一些操作方法需要同步(synchronized)。

    2。netConnection核心代碼解析:

    netConnection類的實現(xiàn)思想很簡單,就是設(shè)置一些request屬性和對于GET方法構(gòu)造一個特殊的URL。更重要的是其作者對http協(xié)議的深入理解、嚴(yán)謹(jǐn)?shù)拇a風(fēng)格值得吾輩學(xué)習(xí)、研究。這也是本人分析其核心代碼的一大原因。

    /**
    * 實現(xiàn)了連接邏輯。
    * 調(diào)用者可以在分離的線程中使用netConnection類的靜態(tài)連接。
    * @throws IllegalStateException 如果此方法直接其它類調(diào)用則拋出該異常
    */
    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;
                    
                    //根據(jù)method值,設(shè)置Connector的權(quán)限(READ/READ_WRITE)
                    if (HttpConnection.GET.equals(method)) {
                            permissions = Connector.READ;
                    } else if (HttpConnection.POST.equals(method)) {
                            permissions = Connector.READ_WRITE;
                    }
                    
                    //如果關(guān)閉server代理功能,則構(gòu)造noProxyUrl。
                    //原理:使用timestamp作為該URL中no-proxy參數(shù)值,
                    //        致使server視其為client發(fā)來的新請求。
                    if (disableProxy) {
                            
                            boolean hasQueryParams = false;
                            
                            char[] ca = url.toCharArray();
                            //判斷原URL中是否含有參數(shù)
                            for (int loop = 0; loop < url.length(); loop++) {
                                    
                                    if (ca[loop] == '?') {
                                            hasQueryParams = true;
                                            break;
                                    }
                            }
                            
                            //由于需要多次字符串拼接,所以使用可提供效率的StringBuffer類
                            StringBuffer noProxyUrl = new StringBuffer();

                            //將原URL內(nèi)容復(fù)制到noProxyUrl
                            noProxyUrl.append(url);

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

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

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

                    //如果request權(quán)限為READ(即request方法為GET),
                    //則需要設(shè)置http request屬性的Range。
                    //原理:設(shè)置http request屬性的Range后的,
                    //        server接收到該request后將把response數(shù)據(jù)分成小部分發(fā)回。
                    //        從而避免了部分運營商對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權(quán)限為READ_WRITE(即request方法為POST),
                    //那么設(shè)置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;
                    //如果程序運行在多線程模式,則在異常發(fā)生后需要喚醒其它睡眠的線程繼續(xù)run
                    if (detached) {
                            forceNotify();
                    }
                    
                    return;
                    
            } finally {

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

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

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

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

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

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

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


    五、參考資料:

    聯(lián)系netConnection作者:JAY-F
    源代碼下載
    HTTP/1.1定義


    不知道大家會更喜歡哪一種封裝呢?


    HttpConnectionWrapper嗎?
    他的調(diào)用方法:


            Wait w = (Wait) display.getCurrent();
            HttpConnection conn = null;
            InputStream in = null;
            
            try {
                conn = new HttpConnectionWrapper( (HttpConnection) Connector.open( url ) );
                conn.setRequestProperty( "User-Agent", "Profile/MIDP-1.0 Configuration/CLDC-1.0" );
                conn.setRequestProperty( "Connection", "close" );
                conn.setRequestProperty( "Send-HTTP-Log-To", "ericgiguere@ericgiguere.com" );
                int rc = conn.getResponseCode();
                w.update( "Response code " + rc );
                in = conn.openInputStream();
                
                for( int i = 0; i < 100; ++i ){
                    if( in.read() == -1 ) break;
                }


    封裝類示意:


    /**
     * A wrapper for the HttpConnection interface that logs method
     * calls and state transitions. Wrap a connection immediately
     * after obtaining it from Connector.open. Information is logged
     * according to the log level set the "httpwrapper" logger.
     */

    public class HttpConnectionWrapper implements HttpConnection {



    還是NetConnection?
    他的調(diào)用方法:

    NetConnection.connect("http://www.molon.com.cn/",data,HttpConnection.GET,...);


    封裝類示意:


    /**
     * This class provides robust network connectivity and exception handling
     * over an unreliable MIDP HttpConnection.
     *
     * In addition the caller may perform a combination of any of the below
     * functions.
     *
     * - Proxy-server thwarting
     * - HTTP range requests
     * - Thread-separated connections
     *
     * @author Jason Fuerstenberg (http://www.jay-f.jp)
     * @version 2004/03/15
     */
    public final class NetConnection implements Runnable {

    主站蜘蛛池模板: 亚洲女人18毛片水真多| 亚洲熟妇无码av另类vr影视| 国产精品1024永久免费视频| 亚洲av日韩综合一区久热| 亚洲高清免费视频| 日本免费在线中文字幕| 亚洲hairy多毛pics大全| 国产AV无码专区亚洲AV漫画| 免费人成在线观看69式小视频| 蜜桃传媒一区二区亚洲AV| 亚洲AV永久无码精品| 热99re久久免费视精品频软件| 三年片免费观看大全国语| 亚洲娇小性xxxx| 国产成人麻豆亚洲综合无码精品| 成年网站免费视频A在线双飞| 亚欧洲精品在线视频免费观看| 亚洲一线产区二线产区精华| MM131亚洲国产美女久久| 久久久久久久91精品免费观看| 久久成人永久免费播放| 亚洲综合av一区二区三区| 久久噜噜噜久久亚洲va久| 四虎免费久久影院| 免费国产成人高清在线观看网站| 中文字幕一区二区三区免费视频| 亚洲人成网站免费播放| 97se亚洲综合在线| 亚洲色WWW成人永久网址| 国产男女猛烈无遮档免费视频网站| 在线免费中文字幕| 中国好声音第二季免费播放| 朝桐光亚洲专区在线中文字幕| 亚洲小视频在线播放| 亚洲国产成人精品不卡青青草原| 亚洲av日韩片在线观看| 岛国片在线免费观看| 国产精品久久免费| 亚洲视频免费在线观看| 香蕉免费看一区二区三区| 日韩大片在线永久免费观看网站|