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

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

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

    騎豬闖天下

    J2ME隨筆,記錄成長的腳步

    統計

    留言簿(3)

    閱讀排行榜

    評論排行榜

    [J2ME]J2ME連網&不同運營商網絡的連網

    隨著中國移動,聯通,電信的先后獲得3G牌照,移動軟件開發必定會熱起來,無論是現在熱火朝天的J2ME 版的UCWEB,QQ,還是移動的飛信等都是必須連網的,因此掌握J2ME的網絡編程是我們程序員的一門絕技,而通用連接框架則是網絡編程的基礎。

      這篇文章主要介紹

      1. 通用連接框架的基礎知識。

      2. 中國環境下的網絡開發

      請注意本文假定讀者熟悉 J2ME 環境中的 MIDlet 開發。需要在系統中安裝 J2ME 開發環境才能編譯代碼示例,以及 J2ME Wireless Toolkit(WTK) 的安裝指導,請參閱文章末尾參考資料 的小結。

      GCF 是一組在 javax.microedition.io 包中定義的接口。圖 1 顯示了 GCF 的類層次結構。
     

    通用連接框架介紹

    圖 1. 通用連接框架的類層次結構
     

      在 GCF 中共定義了七個接口 ,其中 Connection 是根。注意同時提供了對數據包(packet)和流連接的支持。正如您設想的那樣,沿著層次結構向下就會發現提供更多功能的接口。例如, StreamConnection 支持輸入和輸出流, ContentConnection 擴展了 StreamConnection 以支持對流的內容類型、數據長度和編碼格式的確定。

      Connector 類用于在 GCF 中打開類型的連接。下面可以看到 Connector 類中的 open() 方法的格式:Connector.Open("protocol:address;parameters"); Open方法會根據你提供的字符串參數進行Connection的綁定。

      GCF 在支持不同的連接協議方面特別靈活。在請求打開一個連接時, Connector 類使用其 Class.forName() 方法搜索實現了所請求的協議的類。如果找到這個類,就返回一個實現了 Connection 接口的對象。

      下面是一些常用打開一個Connection的方法:
     

    Connector.Open("socket://www.lexun.com:80"); //TCP套接字通訊連接建立
    Connector.Open(
    "http://www.itpub.net");//
    通過Http協議數據通信
    Connector.Open(
    "datagram://www.ucweb.com:1000");//數據報套接字通訊建立
    Connector.Open(
    "file://makefile.txt");//
    訪問手機文件
    Connection conn
    = Connector.open("comm:0; baudrate=5333");//基于串口協議的數據通信

    連接框架的用法


      七種創建連接的方法,下面是代碼示例

    public static Connection open(String name)
      
    public static
    Connection open(String name)
      
    public static Connection open(String name, int mode, boolean
    timeouts)
      
    public static
    DataInputStream openDataInputStream(String name)
      
    public static
    DataOutputStream openDataOutputStream(String name)
      
    public static
    InputStream openInputStream(String name)
      
    public static
    OutputStream openOutputStream(String name)

      Connector 構建了7個靜態的方法,上面方法,具體的相關用法以及參數說明可以查看APIs文檔。
    通訊連接的IO數據流過程基本步驟分別是建立連接、
    網絡通訊、連接關閉。
    1、建立連接,創建與服務端的連接初始化以及完成連接過程。
    2、數據通訊,在連接已建立的基礎上進行數據的
    交換以及完成通訊過程。
    3、完成通訊之后即關閉網絡通訊連接,釋放資源。

    使用小秘密:

      在程序調用Connector.open()相關方法的時候,如果您的J2ME程序是沒有經過簽名的,系統會彈出一個是否允許的對話框,其實,我們在開發的過程中也可以調用下面的代碼進行一些權限的判斷,然后做出適當的動作。
    MIDlet. checkPermission("javax.microedition.io.Connector.file.read");
    MIDlet. checkPermission("javax.microedition.io.Connector.file.write");
    MIDlet.checkPermission("javax.microedition.io.Connector.http")
    其他一些權限檢查請查看相關的APIs文檔。

    簡單用法代碼片段

    // Create a ContentConnection
    String url = "http://www.corej2me.com"

    ContentConnection connection
    = (ContentConnection) Connector.open(url);
    // With
    the connection, open a stream
    InputStream iStrm
    =
    connection.openInputStream();
    //
    ContentConnection includes a length method
    int length = (int
    ) connection.getLength();
    if (length != -1
    )
    {
      
    byte imageData[] = new byte
    [length];
      
    // Read the data into an array

      iStrm.read(imageData);
    }

    3 .1 中國的網絡環境

    運營商

    代理名稱

    用法介紹

    直連名稱

    用法

    中國移動

    CMWAP

    CMWAP是中國移動的GPRS代理上網。

    創建連接的時候,不能直接采用

    Connector.open("target address");

    而是采用代理的方式進行連接

    具體相關的創建代碼是代理的方式。

    代理地址是:10.0.0.172

    代理Header是:X-Online-Host

    CMNET

    3家運營上的直連方式,創建連接跟PC無異。

    中國聯通

    UNIWAP

    UNIWAP是中國聯通退出的一種上網模式。類似于中國移動。具體創建連接的方式跟中國移動類似。

    代理地址是:10.0.0.172

    代理Header是:X-Online-Host

    在處理網關的時候可能會有一些細致的差別,比如在發送Header數據的時候。

    UNINET

    中國電信

    CTWAP

    CTWAP 是中國電信最近推出的上網方式。到目前為止我還沒有找到j2me可以上ctwap的方式,網上只是提到了代理地址是10.0.0.200,header key是啥,該傳什么值,暫時還不知道,如果有讀者知道的可以聯系我(gooogledev@gmail.com)

    CTNET

    3 .2 HttpConnection 介紹

      我們先來講解下HttpConnection相關的方法。

      現在您已經看到 GCF 是如何支持不同類型的連接的,并且開發了我們的第一個連網 MIDlet,現在可以更深入地分析 MIDP 中對 HTTP 的支持。我們將首先從一個更新過的層次結構圖開始,它表明了哪個類提供了對 HTTP 連接的支持。

    圖:支持 HTTP 的 GCF 類


      原來的 MIDP 1.0 規范只要求設備支持 HTTP 連接協議,而更新的 MIDP 2.0 規范要求同時支持 HTTP 和 HTTPS,后者提供了對更安全 style="COLOR: #000000" target=_blank>安全的網絡連接的支持。使用這些協議的 API 分別是 HttpConnection 和 HttpConnection 。除了這些強制性的協議,設備制造商可能會選擇支持更多的通信協議,如數據包或者套接字。雖然有時會方便一些,但是您應當了解使用特定于廠商的協議會影響應用程序到其他設備的可移植性。

      請求和響應協議:HTTP 和 HTTPS 都是請求/響應協議。客戶機發送請求,而服務器 style="COLOR: #000000" target=_blank>服務器發送響應。在繼續后面的內容之前,我們將分析客戶請求和服務器響應的各個方面。

      客戶請求:客戶請求(client request),有時稱為請求實體,由以下三個部分組成:

    · 請求方法

    · 頭

    · 正文

      我們將詳細討論這三個部分。

      請求方法:請求方法(request method)確定數據如何發送給遠程資源。可以使用的三種方法是 GET、 POST 和 HEADER 。使用 GET 時,數據是作為 URL 的一部分發送的。使用 POST 時,所有客戶機數據都是在與建立連接的請求不同的、單獨的流中發送的。 HEADER 請求不向服務器發送任何數據。相反, HEADER 請求只是描述(meta)關于遠程資源的信息。

    用 GET 打開一個 HTTP 連接

    String url = "http://www.ucweb.com?size=large";

    HttpConnection http = null;

    http = (HttpConnection) Connector.open(url);

    http.setRequestMethod(HttpConnection.GET);

    setRequestProperty("User-Agent", "Openwave");

    Openwave -- 是一個比較出名的Wap瀏覽器廠商,因此設置這個UA,移動網關一般可以通過。

    用 POST 打開一個 HTTP 連接

    String url = "http://www.ucweb.com",

    tmp = "test data here";

    OutputStream ostrm = null;

    HttpConnection http = null;

    http = (HttpConnection) Connector.open(url);

    http.setRequestMethod(HttpConnection.POST);

    // Send client body

    ostrm = http.openOutputStream();

    byte bytes[] = tmp.getBytes();

    for(int i = 0; i < bytes.length; i++)

    {

     os.write(bytes[i]);

    }

    os.flush();

      POST/GET 請求一般都是在網頁中的Form進行指定,如果你亂用這些請求可能會導致一些意外的效果,比如Form指定POST請求,則用GET請求就會出問題。

      上面的請求過程只是完成一次HTTP請求中的客戶端請求,下面我們來看下服務器是怎么響應的。

      服務器響應:當服務器收到并處理了客戶請求后,它必須打包并發送響應。與客戶請求一樣,服務器響應有三個部分:

    · 狀態行

    · 頭

    · 正文

      狀態行:顧名思義, 服務器狀態行(server status line)通知客戶機其請求的結果。HTTP 將狀態行代碼分為以下三大類:

    · 1xx是提供信息 。

    · 2xx是成功 。

    · 3xx是重定向 。

    · 4xx是客戶機錯誤 。

    · 5xx是服務器錯誤。

      更加具體的響應代碼請查看HTTP相關協議文檔。

      介紹一本書《Java Servlets 2.3 編程指南》此書狀態代碼有詳細的介紹。

      服務器狀態行包括在服務器上運行的協議版本號、狀態碼和表示返回代碼的文字消息。下面是有效的狀態行的幾個例子:

    · “HTTP/1.1 200 OK”

    · “HTTP/1.1 400 Bad Request”

    · “HTTP/1.1 500 Internal Server Error”

      頭:與客戶機不同,服務器可以通過頭字段發送信息。

      顯示了三種最常用的、提取來自服務器的頭信息的方法。

    String  getHeaderField(int n) Get header field value looking up by index

    String  getHeaderField(String name) Get header field value looking up by name

    String  getHeaderFieldKey(int n) Get header field key using index

      注意:雖然系統給你提供了這些方法,但建議你通信的時候別這么做,因為有可能有些地方的移動網關會過濾掉你這些參數。至于該怎么傳輸你想要的數據,那就看各位的私有的協議是咋通訊了。

      在開發網絡軟件,很多時候是需要調試的,因此一款好的抓包工具對我們的工作幫助是很大的,在這里我推薦使用iris http://www.eeye.com/html/Products/Iris/index.html


    HttpConnection API

    方法

    說明

    long getDate()

    得到頭字段日期

    long getExpiration()

    得到頭字段失效時間

    String getFile()>

    從 URL 得到文件名

    int getHeaderField(int n)

    通過查詢索引得到頭字段值

    String getHeaderField(String name)

    通過查詢名字得到頭字段值

    long getHeaderFieldDate(String name, long def)

    得到作為 long 型的指定字段(表示日期)

    int getHeaderFieldInt(String name, int def)

    得到作為整數的指定字段

    String getHeaderFieldKey(int n)

    使用索引得到頭字段鍵

    String getHost()

    根據 URL 得到主機

    long getLastModified()

    得到最后修改的字段值

    String getPort()

    從 URL 得到端口

    String getProtocol()

    從 URL 得到 協議

    String getQuery()

    得到查詢字符串(只對 GET 請求有效)

    String getRef()

    得到 URL 的引用部分

    String getRequestMethod()

    得到請求方法的當前設置( GET 、 POST 或者 HEAD )

    String getRequestProperty(String key)

    得到一種請求屬性的當前設置

    int getResponseCode()

    得到響應碼(數字值)

    String getResponseMessage()

    得到響應消息(文字值)

    String getURL()

    得到整個 URL

    void setRequestMethod(String method)

    設置請求方法( GET 、 POST 或者 HEAD )

    void setRequestProperty(String key, String value)

    設置請求屬性(頭信息)


    注意點:我們在使用Http的過程中最常用的方法就是getResponseCode(); openInputStream()等操作。

    HttpConnection的實現原理,并不是在open的時候去連網,而是你做getResponseCode();

    openInputStream(); openOutputStream(); 等讀寫操作的時候才真正的去創建。因此只是調用open()是不會觸發連網動作的。

    HttpConnnection在底層的實現上也是采用TCP Socket的方式進行數據的讀寫。


    3 .3 創建GPRS連接

      在中國目前知道的可以連接成功的有中國移動,跟中國聯通,由于移動起步比較早,相對網關,以及基站方面的建設要好于聯通,而且基于移動方面的軟件也相對多而且成熟,因此聯通在建設GPRS方面就向移動靠攏,原則上來說,聯通是無縫兼容移動的,但是也不保證有細微的差別,讀者在開發網絡環境下的軟件的時候,最后經過兩個網絡的驗證才能保證產品的網絡質量。至于電信,由于電信剛接手移動通信,因此在網絡的建設,經驗方面相對差點,因此到目前為止,我還沒有找到一個辦法連接ctwap。這里只介紹cmwap,uniwap連接的創建方式以及注意事項。


      打開GPRS Http連接的代碼清單

      HttpConnection sHttp = (HttpConnection) .Connector.open("http://10.0.0.172:80");

      sHttp.setRequestProperty("X-Online-Host","wap.ucweb.com");

      代碼就這么簡單,不過這里需要注意的Header的發送。


      User-Agent -- 非常重要的參數,很多網站對這個字段很敏感,如果這個字段發送有誤,或者含糊不清,及有可能對方服務器會相應500,或者其他錯誤。

      Connection -- 向對方服務器請求連接的模式,Close 請求一次就關閉,Keep-Alive 保持連接,原則上說來,keep-alive可以達到最優化的速度,但是也是需要客戶端跟服務器同時支持才行。建議采用close模式,這樣做就比較穩妥了。


      還有其他一些參數,可以參考HTTP相關的協議說明。

    3 .4  從網絡上獲取圖片

      經過上面的基礎知識以及中國環境下相關的網絡介紹,這一單節,我們來點實戰的,我們的Demo將采用HttpConnection方式從網絡上獲取一張圖片,并顯示在手機屏幕

      我們在這個Demo中將會講解其中的要點,具體相關的完整的源代碼請點擊這下載

      下面是相關的實現代碼,代碼里有相當詳細的注釋。

    import javax.microedition.lcdui.*;

    import java.io.IOException;

    import javax.microedition.io.HttpConnection;

    import javax.microedition.io.Connection;

    import javax.microedition.io.Connector;

    import java.io.InputStream;

    import java.io.ByteArrayOutputStream;


    /**


    * <p>Title: </p>

    *

    * <p>Description: </p>

    *

    * <p>Copyright: Copyright (c) 2009</p>

    *

    * <p>Company: </p>

    *

    * @author not attributable

    * @version 1.0


    */

    public class ImageForm extends Form implements CommandListener {




        Command iHttp
    = new Command("http"
    , Command.BACK, Command.ITEM);

          Command iExit
    = new Command("Exit", Command.EXIT, 1
    );


        
    public
    ImageForm() {

            super(
    "ShowImage"
    );

            try {

                jbInit();

            }

            catch(Exception e) {

                e.printStackTrace();

            }

        }


        
    private
    void jbInit() throws Exception {

            
    // Set up this Displayable to listen to
    command events

            setCommandListener(this);

            
    // add the Exit
    command

            addCommand(iExit);



            addCommand(iHttp);

        }


        
    public
    void commandAction(Command aCommand, Displayable aDisplayable) {

            
    /** @todo Add command handling code */


            
    if (aCommand == iExit) {

                
    //
    stop the MIDlet

                HttpDemo.quitApp();

            }
    else if(aCommand ==
    iHttp){

                startRqeusetHttpImage();

            }

        }


        
    /**


        
    * startReqeustSocketImage

        
    */


        
    private void startReqeustSocketImage() {

          

        }


        
    /**


        
    * 執行請求

        
    *


        
    */

        
    private void startRqeusetHttpImage() {

            
    //
    一般來說,操作網絡等有阻塞的動作最好是啟動一個線程。

            
    new
    Thread() {

                
    public
    void run() {

                     HttpConnection sHttp
    = null
    ;

                     InputStream sIs
    = null
    ;

                    try {

                        append(
    "Strart Request"
    );

                        append(
    ""
    );

                        sHttp
    =  (HttpConnection) openConnection("http://java.chinaitlab.com/UploadFiles_8734/200903/20090320092412894.png", 0
    );

                        sHttp.setRequestMethod(HttpConnection.GET);
    //
    設置請求方法,如果不設置的話,則系統默認的請求就是GET請求

                        sHttp.setRequestProperty(
    "User-Agent", "Openwave"); //
    設置UA參數

                        sHttp.setRequestProperty(
    "connection", "close"
    );

                      

                        
    int sCode =
    sHttp.getResponseCode();

                        
    if(sCode == 200
    ){

                            sIs
    =
    sHttp.openDataInputStream();

                            
    byte [] sImageData = readDataFromStream(sIs, 512
    );

                            
    if(sImageData != null
    )

                                append(Image.createImage(sImageData,
    0
    , sImageData.length));

                        }

                      


                    }

                    catch (Exception ex1) {

                        append(ex1.toString());

                    }finally{

                        
    //
    一般來說,close數據,一般寫在finally方法,這樣可以保證到如果程序出現任何問題都可以關閉連接,防止連接泄漏

                        try {

                            sIs.close();

                            sHttp.close();

                        } catch (IOException ex) {

                        }

                    }

                }

            }.start();

        }

      

        
    /**


        
    * 創建一個連接

        
    * @param aUrl String


        
    * @param aNetworType int 0--CMNET ; 1--CMWAP

        
    *
    @return Connection

        
    */


          final Connection openConnection(
    String aUrl, int aNetworType){

            Connection sConnection
    = null
    ;

            try{

                
    if (aNetworType == 0
    ) {

                    sConnection
    =
    Connector.open(aUrl);

                }
    else
    {

                    HttpConnection sHttp
    =
    (HttpConnection) Connector.

                                  open(
    "http://10.0.0.172:80"
    );

                    sHttp.setRequestProperty(
    "X-Online-Host"
    ,

                                                   aUrl);

                    sConnection
    =
    sHttp;

                }

            }catch(Exception e){

               append(
    "Open Error=>" +
    e.toString());

            }

             return sConnection;

        }

      

        
    /**


        
    * 從輸入流中讀取數據

        
    *
    @param aIs InputStream

        
    * @param aCache int //
    設置緩存大小,這個參數比較重要,設置大了,速度不一定快,因此得測試根據經驗找個平衡點

        
    * @return byte[]

        
    */


          final
    byte[] readDataFromStream(InputStream aIs, int aCache){

            
    byte[] sData = null
    ;

            java.io.ByteArrayOutputStream bos
    = new
    ByteArrayOutputStream();

            try{

                
    byte[] sCaceh = new byte
    [aCache];

                
    int pos = 0
    ;

                
    int hasRead = 0
    ;

                
    while ((pos = aIs.read(sCaceh, 0, aCache)) != -1
    ) {

                    hasRead
    +=
    pos;

                    bos.write(sCaceh,
    0
    , pos);

                }

                sData
    =
      bos.toByteArray();

            }catch(Exception e){

              

            }

            return sData ;

        }

    }

     

    圖:運行截圖

    3 .5 讀取wml數據

      經過上面的代碼示例,我們知道怎么樣獲取到一張圖片了,此節我將給大家講解下怎么樣去奪取網站的wml數據。廢話少說,我們只需要在上面的基礎上加多一個方法就可以了。


    下面是代碼示例

    import javax.microedition.lcdui.*;

    import java.io.IOException;

    import javax.microedition.io.HttpConnection;

    import javax.microedition.io.Connection;

    import javax.microedition.io.Connector;

    import java.io.InputStream;

    import java.io.ByteArrayOutputStream;


    /**


    * <p>Title: </p>

    *

    * <p>Description: </p>

    *

    * <p>Copyright: Copyright (c) 2009</p>

    *

    * <p>Company: </p>

    *

    * @author not attributable

    * @version 1.0


    */

    public class ImageForm extends Form implements CommandListener {




        Command iHttp
    = new Command("http"
    , Command.BACK, Command.ITEM);

          Command iExit
    = new Command("Exit", Command.EXIT, 1
    );


        
    public
    ImageForm() {

            super(
    "ShowImage"
    );

            try {

                jbInit();

            }

            catch(Exception e) {

                e.printStackTrace();

            }

        }


        
    private
    void jbInit() throws Exception {

            
    // Set up this Displayable to listen to
    command events

            setCommandListener(this);

            
    // add the Exit
    command

            addCommand(iExit);



            addCommand(iHttp);

        }


        
    public
    void commandAction(Command aCommand, Displayable aDisplayable) {

            
    /** @todo Add command handling code */


            
    if (aCommand == iExit) {

                
    //
    stop the MIDlet

                HttpDemo.quitApp();

            }
    else if(aCommand ==
    iHttp){

                startRqeusetHttpImage();

            }

        }


        
    /**


        
    * startReqeustSocketImage

        
    */


        
    private void startReqeustSocketImage() {

          

        }


        
    /**


        
    * 執行請求

        
    *


        
    */

        
    private void startRqeusetHttpImage() {

            
    //
    一般來說,操作網絡等有阻塞的動作最好是啟動一個線程。

            
    new
    Thread() {

                
    public
    void run() {

                     HttpConnection sHttp
    = null
    ;

                     InputStream sIs
    = null
    ;

                    try {

                        append(
    "Strart Request"
    );

                        append(
    ""
    );

                        sHttp
    =  (HttpConnection) openConnection("http://java.chinaitlab.com/UploadFiles_8734/200903/20090320092412894.png", 0
    );

                        sHttp.setRequestMethod(HttpConnection.GET);
    //
    設置請求方法,如果不設置的話,則系統默認的請求就是GET請求

                        sHttp.setRequestProperty(
    "User-Agent", "Openwave"); //
    設置UA參數

                        sHttp.setRequestProperty(
    "connection", "close"
    );

                      

                        
    int sCode =
    sHttp.getResponseCode();

                        
    if(sCode == 200
    ){

                            sIs
    =
    sHttp.openDataInputStream();

                            
    byte [] sImageData = readDataFromStream(sIs, 512
    );

                            
    if(sImageData != null
    )

                                append(Image.createImage(sImageData,
    0
    , sImageData.length));

                        }

                      


                    }

                    catch (Exception ex1) {

                        append(ex1.toString());

                    }finally{

                        
    //
    一般來說,close數據,一般寫在finally方法,這樣可以保證到如果程序出現任何問題都可以關閉連接,防止連接泄漏

                        try {

                            sIs.close();

                            sHttp.close();

                        } catch (IOException ex) {

                        }

                    }

                }

            }.start();

        }

      

        
    /**


        
    * 創建一個連接

        
    * @param aUrl String


        
    * @param aNetworType int 0--CMNET ; 1--CMWAP

        
    *
    @return Connection

        
    */


          final Connection openConnection(
    String aUrl, int aNetworType){

            Connection sConnection
    = null
    ;

            try{

                
    if (aNetworType == 0
    ) {

                    sConnection
    =
    Connector.open(aUrl);

                }
    else
    {

                    HttpConnection sHttp
    =
    (HttpConnection) Connector.

                                  open(
    "http://10.0.0.172:80"
    );

                    sHttp.setRequestProperty(
    "X-Online-Host"
    ,

                                                   aUrl);

                    sConnection
    =
    sHttp;

                }

            }catch(Exception e){

               append(
    "Open Error=>" +
    e.toString());

            }

             return sConnection;

        }

      

        
    /**


        
    * 從輸入流中讀取數據

        
    *
    @param aIs InputStream

        
    * @param aCache int //
    設置緩存大小,這個參數比較重要,設置大了,速度不一定快,因此得測試根據經驗找個平衡點

        
    * @return byte[]

        
    */


          final
    byte[] readDataFromStream(InputStream aIs, int aCache){

            
    byte[] sData = null
    ;

            java.io.ByteArrayOutputStream bos
    = new
    ByteArrayOutputStream();

            try{

                
    byte[] sCaceh = new byte
    [aCache];

                
    int pos = 0
    ;

                
    int hasRead = 0
    ;

                
    while ((pos = aIs.read(sCaceh, 0, aCache)) != -1
    ) {

                    hasRead
    +=
    pos;

                    bos.write(sCaceh,
    0
    , pos);

                }

                sData
    =
      bos.toByteArray();

            }catch(Exception e){

              

            }

            return sData ;

        }

    }

    圖:運行截圖

    3 .6 總結

      經過上面的代碼實戰以后,相信讀者在對網絡編程方面也有了基礎的認識,至于一些深入性的問題,只能等待讀者們在實戰的時候去做一些相關的研究了,這里不能面面俱到。

    4  注意事項
    1. 中國移動環境下的
    網絡編程

    2. 請求參數的發送。特別是UA,Conneciton等參數

    3. Cache 的大小。主要是保證網絡讀取速度的最優化

    4. 手機各個平臺對應的APIs的適配。主要是程序的兼容性考慮

    5. 虛擬機平臺相關的網絡底層實現,有些虛擬機不支持同時并發多個網絡線程。程序的兼容性考慮


    posted on 2010-04-02 13:33 騎豬闖天下 閱讀(591) 評論(0)  編輯  收藏


    只有注冊用戶登錄后才能發表評論。


    網站導航:
     
    主站蜘蛛池模板: 免费国产成人午夜私人影视| 亚洲狠狠成人综合网| 国产免费观看青青草原网站| 久久久久久国产精品免费无码| 日本激情猛烈在线看免费观看| jiz zz在亚洲| 亚洲午夜久久久久久尤物 | 亚洲熟妇AV日韩熟妇在线| 亚洲AV无码久久寂寞少妇| 亚洲成a人片在线观看日本麻豆| 色婷婷7777免费视频在线观看| 香蕉成人免费看片视频app下载| 一级毛片无遮挡免费全部| 国产精品久久久久久亚洲影视| 亚洲a∨无码男人的天堂| 久久久亚洲精品视频| 亚洲精品你懂的在线观看| 亚洲视频在线免费| 四虎永久免费影院| 日本a级片免费看| 午夜a级成人免费毛片| 国产乱子精品免费视观看片| 99精品视频免费观看| 久久青草免费91线频观看不卡| 99久久免费国产精品热| 久久免费香蕉视频| 一级毛片视频免费| 一级全免费视频播放| 一级成人毛片免费观看| jzzjzz免费观看大片免费| 一级毛片aa高清免费观看| japanese色国产在线看免费| 午夜免费国产体验区免费的| 羞羞视频在线观看免费| 久久99久久成人免费播放| 美女网站在线观看视频免费的| 国产伦精品一区二区免费| 99久久99这里只有免费的精品| 免费无码一区二区三区蜜桃| 久9久9精品免费观看| 100部毛片免费全部播放完整|