隨著中國移動,聯(lián)通,電信的先后獲得3G牌照,移動軟件開發(fā)必定會熱起來,無論是現(xiàn)在熱火朝天的J2ME 版的UCWEB,QQ,還是移動的飛信等都是必須連網(wǎng)的,因此掌握J(rèn)2ME的網(wǎng)絡(luò)編程是我們程序員的一門絕技,而通用連接框架則是網(wǎng)絡(luò)編程的基礎(chǔ)。
這篇文章主要介紹
1. 通用連接框架的基礎(chǔ)知識。
2. 中國環(huán)境下的網(wǎng)絡(luò)開發(fā)
請注意本文假定讀者熟悉 J2ME 環(huán)境中的 MIDlet 開發(fā)。需要在系統(tǒng)中安裝 J2ME 開發(fā)環(huán)境才能編譯代碼示例,以及 J2ME Wireless Toolkit(WTK) 的安裝指導(dǎo),請參閱文章末尾參考資料 的小結(jié)。
GCF 是一組在 javax.microedition.io 包中定義的接口。圖 1 顯示了 GCF 的類層次結(jié)構(gòu)。
通用連接框架介紹

圖 1. 通用連接框架的類層次結(jié)構(gòu)
在 GCF 中共定義了七個接口 ,其中 Connection 是根。注意同時(shí)提供了對數(shù)據(jù)包(packet)和流連接的支持。正如您設(shè)想的那樣,沿著層次結(jié)構(gòu)向下就會發(fā)現(xiàn)提供更多功能的接口。例如, StreamConnection 支持輸入和輸出流, ContentConnection 擴(kuò)展了 StreamConnection 以支持對流的內(nèi)容類型、數(shù)據(jù)長度和編碼格式的確定。
Connector 類用于在 GCF 中打開類型的連接。下面可以看到 Connector 類中的 open() 方法的格式:Connector.Open("protocol:address;parameters"); Open方法會根據(jù)你提供的字符串參數(shù)進(jìn)行Connection的綁定。
GCF 在支持不同的連接協(xié)議方面特別靈活。在請求打開一個連接時(shí), Connector 類使用其 Class.forName() 方法搜索實(shí)現(xiàn)了所請求的協(xié)議的類。如果找到這個類,就返回一個實(shí)現(xiàn)了 Connection 接口的對象。
下面是一些常用打開一個Connection的方法:
Connector.Open("socket://www.lexun.com:80"); //TCP套接字通訊連接建立
Connector.Open("http://www.itpub.net");//通過Http協(xié)議數(shù)據(jù)通信
Connector.Open("datagram://www.ucweb.com:1000");//數(shù)據(jù)報(bào)套接字通訊建立
Connector.Open("file://makefile.txt");//訪問手機(jī)文件
Connection conn = Connector.open("comm:0; baudrate=5333");//基于串口協(xié)議的數(shù)據(jù)通信
連接框架的用法
七種創(chuàng)建連接的方法,下面是代碼示例
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 構(gòu)建了7個靜態(tài)的方法,上面方法,具體的相關(guān)用法以及參數(shù)說明可以查看APIs文檔。
通訊連接的IO數(shù)據(jù)流過程基本步驟分別是建立連接、網(wǎng)絡(luò)通訊、連接關(guān)閉。
1、建立連接,創(chuàng)建與服務(wù)端的連接初始化以及完成連接過程。
2、數(shù)據(jù)通訊,在連接已建立的基礎(chǔ)上進(jìn)行數(shù)據(jù)的交換以及完成通訊過程。
3、完成通訊之后即關(guān)閉網(wǎng)絡(luò)通訊連接,釋放資源。
使用小秘密:
在程序調(diào)用Connector.open()相關(guān)方法的時(shí)候,如果您的J2ME程序是沒有經(jīng)過簽名的,系統(tǒng)會彈出一個是否允許的對話框,其實(shí),我們在開發(fā)的過程中也可以調(diào)用下面的代碼進(jìn)行一些權(quán)限的判斷,然后做出適當(dāng)?shù)膭幼鳌?br />
MIDlet. checkPermission("javax.microedition.io.Connector.file.read");
MIDlet. checkPermission("javax.microedition.io.Connector.file.write");
MIDlet.checkPermission("javax.microedition.io.Connector.http")
其他一些權(quán)限檢查請查看相關(guān)的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 中國的網(wǎng)絡(luò)環(huán)境
運(yùn)營商
|
代理名稱
|
用法介紹
|
直連名稱
|
用法
|
中國移動
|
CMWAP
|
CMWAP是中國移動的GPRS代理上網(wǎng)。
創(chuàng)建連接的時(shí)候,不能直接采用
Connector.open("target address");
而是采用代理的方式進(jìn)行連接
具體相關(guān)的創(chuàng)建代碼是代理的方式。
代理地址是:10.0.0.172
代理Header是:X-Online-Host
|
CMNET
|
3家運(yùn)營上的直連方式,創(chuàng)建連接跟PC無異。
|
中國聯(lián)通
|
UNIWAP
|
UNIWAP是中國聯(lián)通退出的一種上網(wǎng)模式。類似于中國移動。具體創(chuàng)建連接的方式跟中國移動類似。
代理地址是:10.0.0.172
代理Header是:X-Online-Host
在處理網(wǎng)關(guān)的時(shí)候可能會有一些細(xì)致的差別,比如在發(fā)送Header數(shù)據(jù)的時(shí)候。
|
UNINET
|
中國電信
|
CTWAP
|
CTWAP 是中國電信最近推出的上網(wǎng)方式。到目前為止我還沒有找到j(luò)2me可以上ctwap的方式,網(wǎng)上只是提到了代理地址是10.0.0.200,header key是啥,該傳什么值,暫時(shí)還不知道,如果有讀者知道的可以聯(lián)系我(gooogledev@gmail.com)
|
CTNET
|
3 .2 HttpConnection 介紹
我們先來講解下HttpConnection相關(guān)的方法。
現(xiàn)在您已經(jīng)看到 GCF 是如何支持不同類型的連接的,并且開發(fā)了我們的第一個連網(wǎng) MIDlet,現(xiàn)在可以更深入地分析 MIDP 中對 HTTP 的支持。我們將首先從一個更新過的層次結(jié)構(gòu)圖開始,它表明了哪個類提供了對 HTTP 連接的支持。

圖:支持 HTTP 的 GCF 類
原來的 MIDP 1.0 規(guī)范只要求設(shè)備支持 HTTP 連接協(xié)議,而更新的 MIDP 2.0 規(guī)范要求同時(shí)支持 HTTP 和 HTTPS,后者提供了對更安全 style="COLOR: #000000" target=_blank>安全的網(wǎng)絡(luò)連接的支持。使用這些協(xié)議的 API 分別是 HttpConnection 和 HttpConnection 。除了這些強(qiáng)制性的協(xié)議,設(shè)備制造商可能會選擇支持更多的通信協(xié)議,如數(shù)據(jù)包或者套接字。雖然有時(shí)會方便一些,但是您應(yīng)當(dāng)了解使用特定于廠商的協(xié)議會影響應(yīng)用程序到其他設(shè)備的可移植性。
請求和響應(yīng)協(xié)議:HTTP 和 HTTPS 都是請求/響應(yīng)協(xié)議。客戶機(jī)發(fā)送請求,而服務(wù)器 style="COLOR: #000000" target=_blank>服務(wù)器發(fā)送響應(yīng)。在繼續(xù)后面的內(nèi)容之前,我們將分析客戶請求和服務(wù)器響應(yīng)的各個方面。
客戶請求:客戶請求(client request),有時(shí)稱為請求實(shí)體,由以下三個部分組成:
· 請求方法
· 頭
· 正文
我們將詳細(xì)討論這三個部分。
請求方法:請求方法(request method)確定數(shù)據(jù)如何發(fā)送給遠(yuǎn)程資源。可以使用的三種方法是 GET、 POST 和 HEADER 。使用 GET 時(shí),數(shù)據(jù)是作為 URL 的一部分發(fā)送的。使用 POST 時(shí),所有客戶機(jī)數(shù)據(jù)都是在與建立連接的請求不同的、單獨(dú)的流中發(fā)送的。 HEADER 請求不向服務(wù)器發(fā)送任何數(shù)據(jù)。相反, HEADER 請求只是描述(meta)關(guān)于遠(yuǎn)程資源的信息。
用 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瀏覽器廠商,因此設(shè)置這個UA,移動網(wǎng)關(guān)一般可以通過。
用 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 請求一般都是在網(wǎng)頁中的Form進(jìn)行指定,如果你亂用這些請求可能會導(dǎo)致一些意外的效果,比如Form指定POST請求,則用GET請求就會出問題。
上面的請求過程只是完成一次HTTP請求中的客戶端請求,下面我們來看下服務(wù)器是怎么響應(yīng)的。
服務(wù)器響應(yīng):當(dāng)服務(wù)器收到并處理了客戶請求后,它必須打包并發(fā)送響應(yīng)。與客戶請求一樣,服務(wù)器響應(yīng)有三個部分:
· 狀態(tài)行
· 頭
· 正文
狀態(tài)行:顧名思義, 服務(wù)器狀態(tài)行(server status line)通知客戶機(jī)其請求的結(jié)果。HTTP 將狀態(tài)行代碼分為以下三大類:
· 1xx是提供信息 。
· 2xx是成功 。
· 3xx是重定向 。
· 4xx是客戶機(jī)錯誤 。
· 5xx是服務(wù)器錯誤。
更加具體的響應(yīng)代碼請查看HTTP相關(guān)協(xié)議文檔。
介紹一本書《Java Servlets 2.3 編程指南》此書狀態(tài)代碼有詳細(xì)的介紹。
服務(wù)器狀態(tài)行包括在服務(wù)器上運(yùn)行的協(xié)議版本號、狀態(tài)碼和表示返回代碼的文字消息。下面是有效的狀態(tài)行的幾個例子:
· “HTTP/1.1 200 OK”
· “HTTP/1.1 400 Bad Request”
· “HTTP/1.1 500 Internal Server Error”
頭:與客戶機(jī)不同,服務(wù)器可以通過頭字段發(fā)送信息。
顯示了三種最常用的、提取來自服務(wù)器的頭信息的方法。
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
注意:雖然系統(tǒng)給你提供了這些方法,但建議你通信的時(shí)候別這么做,因?yàn)橛锌赡苡行┑胤降囊苿泳W(wǎng)關(guān)會過濾掉你這些參數(shù)。至于該怎么傳輸你想要的數(shù)據(jù),那就看各位的私有的協(xié)議是咋通訊了。
在開發(fā)網(wǎng)絡(luò)軟件,很多時(shí)候是需要調(diào)試的,因此一款好的抓包工具對我們的工作幫助是很大的,在這里我推薦使用iris http://www.eeye.com/html/Products/Iris/index.html
HttpConnection API
方法
|
說明
|
long getDate()
|
得到頭字段日期
|
long getExpiration()
|
得到頭字段失效時(shí)間
|
String getFile()>
|
從 URL 得到文件名
|
int getHeaderField(int n)
|
通過查詢索引得到頭字段值
|
String getHeaderField(String name)
|
通過查詢名字得到頭字段值
|
long getHeaderFieldDate(String name, long def)
|
得到作為 long 型的指定字段(表示日期)
|
int getHeaderFieldInt(String name, int def)
|
得到作為整數(shù)的指定字段
|
String getHeaderFieldKey(int n)
|
使用索引得到頭字段鍵
|
String getHost()
|
根據(jù) URL 得到主機(jī)
|
long getLastModified()
|
得到最后修改的字段值
|
String getPort()
|
從 URL 得到端口
|
String getProtocol()
|
從 URL 得到 協(xié)議
|
String getQuery()
|
得到查詢字符串(只對 GET 請求有效)
|
String getRef()
|
得到 URL 的引用部分
|
String getRequestMethod()
|
得到請求方法的當(dāng)前設(shè)置( GET 、 POST 或者 HEAD )
|
String getRequestProperty(String key)
|
得到一種請求屬性的當(dāng)前設(shè)置
|
int getResponseCode()
|
得到響應(yīng)碼(數(shù)字值)
|
String getResponseMessage()
|
得到響應(yīng)消息(文字值)
|
String getURL()
|
得到整個 URL
|
void setRequestMethod(String method)
|
設(shè)置請求方法( GET 、 POST 或者 HEAD )
|
void setRequestProperty(String key, String value)
|
設(shè)置請求屬性(頭信息)
|
注意點(diǎn):我們在使用Http的過程中最常用的方法就是getResponseCode(); openInputStream()等操作。
HttpConnection的實(shí)現(xiàn)原理,并不是在open的時(shí)候去連網(wǎng),而是你做getResponseCode();
openInputStream(); openOutputStream(); 等讀寫操作的時(shí)候才真正的去創(chuàng)建。因此只是調(diào)用open()是不會觸發(fā)連網(wǎng)動作的。
HttpConnnection在底層的實(shí)現(xiàn)上也是采用TCP Socket的方式進(jìn)行數(shù)據(jù)的讀寫。
3 .3 創(chuàng)建GPRS連接
在中國目前知道的可以連接成功的有中國移動,跟中國聯(lián)通,由于移動起步比較早,相對網(wǎng)關(guān),以及基站方面的建設(shè)要好于聯(lián)通,而且基于移動方面的軟件也相對多而且成熟,因此聯(lián)通在建設(shè)GPRS方面就向移動靠攏,原則上來說,聯(lián)通是無縫兼容移動的,但是也不保證有細(xì)微的差別,讀者在開發(fā)網(wǎng)絡(luò)環(huán)境下的軟件的時(shí)候,最后經(jīng)過兩個網(wǎng)絡(luò)的驗(yàn)證才能保證產(chǎn)品的網(wǎng)絡(luò)質(zhì)量。至于電信,由于電信剛接手移動通信,因此在網(wǎng)絡(luò)的建設(shè),經(jīng)驗(yàn)方面相對差點(diǎn),因此到目前為止,我還沒有找到一個辦法連接ctwap。這里只介紹cmwap,uniwap連接的創(chuàng)建方式以及注意事項(xiàng)。
打開GPRS Http連接的代碼清單
HttpConnection sHttp = (HttpConnection) .Connector.open("http://10.0.0.172:80");
sHttp.setRequestProperty("X-Online-Host","wap.ucweb.com");
代碼就這么簡單,不過這里需要注意的Header的發(fā)送。
User-Agent -- 非常重要的參數(shù),很多網(wǎng)站對這個字段很敏感,如果這個字段發(fā)送有誤,或者含糊不清,及有可能對方服務(wù)器會相應(yīng)500,或者其他錯誤。
Connection -- 向?qū)Ψ椒?wù)器請求連接的模式,Close 請求一次就關(guān)閉,Keep-Alive 保持連接,原則上說來,keep-alive可以達(dá)到最優(yōu)化的速度,但是也是需要客戶端跟服務(wù)器同時(shí)支持才行。建議采用close模式,這樣做就比較穩(wěn)妥了。
還有其他一些參數(shù),可以參考HTTP相關(guān)的協(xié)議說明。
3 .4 從網(wǎng)絡(luò)上獲取圖片
經(jīng)過上面的基礎(chǔ)知識以及中國環(huán)境下相關(guān)的網(wǎng)絡(luò)介紹,這一單節(jié),我們來點(diǎn)實(shí)戰(zhàn)的,我們的Demo將采用HttpConnection方式從網(wǎng)絡(luò)上獲取一張圖片,并顯示在手機(jī)的屏幕上
我們在這個Demo中將會講解其中的要點(diǎn),具體相關(guān)的完整的源代碼請點(diǎn)擊這下載。
下面是相關(guān)的實(shí)現(xiàn)代碼,代碼里有相當(dāng)詳細(xì)的注釋。
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() {
}
/**
* 執(zhí)行請求
*
*/
private void startRqeusetHttpImage() {
//一般來說,操作網(wǎng)絡(luò)等有阻塞的動作最好是啟動一個線程。
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);//設(shè)置請求方法,如果不設(shè)置的話,則系統(tǒng)默認(rèn)的請求就是GET請求
sHttp.setRequestProperty("User-Agent", "Openwave"); //設(shè)置UA參數(shù)
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數(shù)據(jù),一般寫在finally方法,這樣可以保證到如果程序出現(xiàn)任何問題都可以關(guān)閉連接,防止連接泄漏
try {
sIs.close();
sHttp.close();
} catch (IOException ex) {
}
}
}
}.start();
}
/**
* 創(chuàng)建一個連接
* @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;
}
/**
* 從輸入流中讀取數(shù)據(jù)
* @param aIs InputStream
* @param aCache int //設(shè)置緩存大小,這個參數(shù)比較重要,設(shè)置大了,速度不一定快,因此得測試根據(jù)經(jīng)驗(yàn)找個平衡點(diǎn)
* @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 ;
}
}

圖:運(yùn)行截圖
3 .5 讀取wml數(shù)據(jù)
經(jīng)過上面的代碼示例,我們知道怎么樣獲取到一張圖片了,此節(jié)我將給大家講解下怎么樣去奪取網(wǎng)站的wml數(shù)據(jù)。廢話少說,我們只需要在上面的基礎(chǔ)上加多一個方法就可以了。
下面是代碼示例
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() {
}
/**
* 執(zhí)行請求
*
*/
private void startRqeusetHttpImage() {
//一般來說,操作網(wǎng)絡(luò)等有阻塞的動作最好是啟動一個線程。
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);//設(shè)置請求方法,如果不設(shè)置的話,則系統(tǒng)默認(rèn)的請求就是GET請求
sHttp.setRequestProperty("User-Agent", "Openwave"); //設(shè)置UA參數(shù)
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數(shù)據(jù),一般寫在finally方法,這樣可以保證到如果程序出現(xiàn)任何問題都可以關(guān)閉連接,防止連接泄漏
try {
sIs.close();
sHttp.close();
} catch (IOException ex) {
}
}
}
}.start();
}
/**
* 創(chuàng)建一個連接
* @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;
}
/**
* 從輸入流中讀取數(shù)據(jù)
* @param aIs InputStream
* @param aCache int //設(shè)置緩存大小,這個參數(shù)比較重要,設(shè)置大了,速度不一定快,因此得測試根據(jù)經(jīng)驗(yàn)找個平衡點(diǎn)
* @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 ;
}
}

圖:運(yùn)行截圖
3 .6 總結(jié)
經(jīng)過上面的代碼實(shí)戰(zhàn)以后,相信讀者在對網(wǎng)絡(luò)編程方面也有了基礎(chǔ)的認(rèn)識,至于一些深入性的問題,只能等待讀者們在實(shí)戰(zhàn)的時(shí)候去做一些相關(guān)的研究了,這里不能面面俱到。
4 注意事項(xiàng)
1. 中國移動環(huán)境下的網(wǎng)絡(luò)編程
2. 請求參數(shù)的發(fā)送。特別是UA,Conneciton等參數(shù)
3. Cache 的大小。主要是保證網(wǎng)絡(luò)讀取速度的最優(yōu)化
4. 手機(jī)各個平臺對應(yīng)的APIs的適配。主要是程序的兼容性考慮
5. 虛擬機(jī)平臺相關(guān)的網(wǎng)絡(luò)底層實(shí)現(xiàn),有些虛擬機(jī)不支持同時(shí)并發(fā)多個網(wǎng)絡(luò)線程。程序的兼容性考慮