我這天,開發(fā)網(wǎng)絡(luò)連接程序,遇到n多問題,都得以解決。
總結(jié)一下。
首先是環(huán)境。
我用的開發(fā)SDK和模擬器都是Sun的,J2ME Wireless Toolkit 2.2
現(xiàn)在UltraEdit下面寫一個(gè)網(wǎng)絡(luò)程序。注意一定要在網(wǎng)絡(luò)連接動(dòng)作時(shí),另外啟動(dòng)一下線程,否則模擬器運(yùn)行會(huì)有錯(cuò)誤。
很不好的代碼:不要使用!!!!!!!!!!
import java.io.InputStream;
import java.io.OutputStream;

import javax.microedition.io.Connector;
import javax.microedition.io.HttpConnection;
import javax.microedition.io.StreamConnection;
import javax.microedition.lcdui.Alert;
import javax.microedition.lcdui.AlertType;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Form;
import javax.microedition.lcdui.TextBox;
import javax.microedition.lcdui.TextField;
import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;

public class MainMidlet extends MIDlet
implements CommandListener


{
private Display display;

public MainMidlet()
{
super();
display = Display.getDisplay(this);
}
private Form f;
private TextField server;
private TextField port;
private TextBox showBox;

protected void startApp() throws MIDletStateChangeException
{
f = new Form("Test Network");
server = new TextField("服務(wù)器","www.google.com",20,TextField.ANY);
port = new TextField("端口","80",4,TextField.NUMERIC);
showBox = new TextBox("連接數(shù)據(jù)", "Init",1024,TextField.ANY);
showBox.addCommand(new Command("返回",Command.BACK,1));
showBox.setCommandListener(this);
f.append(server);
f.append(port);
f.addCommand(new Command("Socket連接",Command.SCREEN,1));
f.addCommand(new Command("Http連接",Command.SCREEN,1));
f.setCommandListener(this);
display.setCurrent(f);
}


protected void pauseApp()
{
// TODO Auto-generated method stub

}


protected void destroyApp(boolean arg0) throws MIDletStateChangeException
{
// TODO Auto-generated method stub

}


public void commandAction(Command arg0, Displayable arg1)
{
if(arg0.getLabel().equals("Socket連接"))

{
socketconnect();
}
else if(arg0.getLabel().equals("Http連接"))

{
httpconnect();
}
else if(arg0.getLabel().equals("返回"))

{
display.setCurrent(f);
}
}
private void socketconnect()

{
StreamConnection socket = null;
InputStream is = null;
OutputStream os = null;

try
{
String name = "http://" + server.getString() + ":" + port.getString();
socket = (StreamConnection)Connector.open(name,Connector.READ_WRITE);
String request = "GET / HTTP/1.0\n\n";
os = socket.openOutputStream();
os.write(request.getBytes());
is = socket.openInputStream();
final int MAX_LENGTH = 128;
byte[] buf = new byte[MAX_LENGTH];
int total = 0;

while(total < MAX_LENGTH)
{
int count = is.read(buf,total, MAX_LENGTH - total);
if(count < 0)

{
break;
}
total += count;
}
String toshow = new String(buf,0,buf.length);
showBox.setString(toshow);
display.setCurrent(showBox);
}catch(Exception ex)

{
Alert al = new Alert("未定義異常", ex.getMessage(), null, AlertType.ALARM);
al.setTimeout(Alert.FOREVER);
display.setCurrent(al,f);

}finally
{
if(is != null)

{

try
{
is.close();
}catch(Exception ex)

{
Alert al = new Alert("未定義異常", ex.getMessage(), null, AlertType.ALARM);
al.setTimeout(Alert.FOREVER);
display.setCurrent(al,f);
}
is = null;
}
if(os != null)

{

try
{
os.close();
}catch(Exception ex)

{
Alert al = new Alert("未定義異常", ex.getMessage(), null, AlertType.ALARM);
al.setTimeout(Alert.FOREVER);
display.setCurrent(al,f);
}
os = null;
}
if(socket != null)

{

try
{
socket.close();
}catch(Exception ex)

{
Alert al = new Alert("未定義異常", ex.getMessage(), null, AlertType.ALARM);
al.setTimeout(Alert.FOREVER);
display.setCurrent(al,f);
}
socket = null;
}
}
}
private void httpconnect()

{
HttpConnection conn = null;
InputStream is = null;
OutputStream os = null;

try
{
String url = "wap.winwap.com";
conn = (HttpConnection)Connector.open("http://10.0.0.172/" + "home.wml");
conn.setRequestProperty("X-Online-Host",url);
conn.setRequestMethod(HttpConnection.GET);
if(conn.getResponseCode() == HttpConnection.HTTP_OK)

{
is = conn.openInputStream();
final int MAX_LENTH = 128;
byte[] buf = new byte[MAX_LENTH];
int total = 0;
while(total < MAX_LENTH)

{
int count = is.read(buf,total,MAX_LENTH - total);
if(count < 0)
break;
total += count;
}
is.close();
String reply = new String(buf,0,total);
showBox.setString(reply);
display.setCurrent(showBox);

}else
{
showBox.insert(String.valueOf(conn.getResponseCode()),showBox.getCaretPosition());
showBox.insert(String.valueOf(HttpConnection.HTTP_OK),showBox.getCaretPosition());
display.setCurrent(showBox);
}
}catch(Exception ex)

{
Alert al = new Alert("未定義異常", ex.getMessage(), null, AlertType.ALARM);
al.setTimeout(Alert.FOREVER);
display.setCurrent(al,showBox);

}finally
{
if(is != null)

{

try
{
is.close();
}catch(Exception ex)

{
Alert al = new Alert("未定義異常", ex.getMessage(), null, AlertType.ALARM);
al.setTimeout(Alert.FOREVER);
display.setCurrent(al,showBox);
}
is = null;
}
if(os != null)

{

try
{
os.close();
}catch(Exception ex)

{
Alert al = new Alert("未定義異常", ex.getMessage(), null, AlertType.ALARM);
al.setTimeout(Alert.FOREVER);
display.setCurrent(al,showBox);
}
os = null;
}
if(conn != null)

{

try
{
conn.close();
}catch(Exception ex)

{
Alert al = new Alert("未定義異常", ex.getMessage(), null, AlertType.ALARM);
al.setTimeout(Alert.FOREVER);
display.setCurrent(al,showBox);
}
conn = null;
}
}
}

}

這段代碼,在模擬器上運(yùn)行很有問題!

這以后,再按鈕就沒有反應(yīng)了,而且,會(huì)有警告warning
警告: 若要避免潛在的死鎖,應(yīng)該在 commandAction() 處理程序之外的其他線程中執(zhí)行
可能會(huì)阻塞的
操作(如網(wǎng)絡(luò)連接)。
模擬器再不能正常鏈接了。無法配置。
===============================================
改代碼如下:
import javax.microedition.io.*;
import java.io.*;
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
public class QueryForm extends TextBox implements CommandListener


{
MIDlet midlet ;
public QueryForm(MIDlet m)

{
super("請(qǐng)輸入網(wǎng)址","http://wap.winwap.com",40,TextField.ANY) ;
midlet = m ;
addCommand(new Command("離開",Command.SCREEN,1)) ;
addCommand(new Command("查詢",Command.SCREEN,1)) ;
setCommandListener(this) ;
}
public void commandAction(Command c,Displayable s)

{
String cmd = c.getLabel() ;
if(cmd.equals("離開"))

{
midlet.notifyDestroyed() ;
}else if(cmd.equals("查詢"))

{
String url = getString() ; //連接網(wǎng)址
WorkThread wt = new WorkThread(url,Display.getDisplay(midlet)) ;
wt.start() ;
}
}
}
import javax.microedition.io.*;
import java.io.*;
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
public class MyHttpClient extends MIDlet


{
Display display ;
public MyHttpClient()

{
display = Display.getDisplay(this) ;
}
public void startApp()

{
display.setCurrent(new QueryForm(this));
}
public void pauseApp()

{
}
public void destroyApp(boolean con)

{
}
}
import javax.microedition.io.*;
import java.io.*;
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
public class WorkThread extends Thread


{
String url ;
Display display ;
public WorkThread(String url,Display d)

{
this.url = url ;
display = d ;
System.out.println("準(zhǔn)備連接:"+this.url) ;
}
public void run()

{
HttpConnection conn = null;
InputStream is = null;
InputStreamReader isr = null ;
StringBuffer line = new StringBuffer("");

try
{
conn = (HttpConnection)Connector.open(url);
System.out.println("內(nèi)容長(zhǎng)度:" + conn.getLength()) ;
is = conn.openInputStream();
isr = new InputStreamReader(is) ;
int ic ;
while( (ic = isr.read()) != -1 )

{
line.append((char)ic) ;
}
}catch (Exception ioe)

{
System.out.println(ioe);
}finally

{
try

{
if(conn!=null)
conn.close();

}catch(Exception e)
{}
}
Alert al = new Alert("查詢結(jié)果",line.toString(),null,AlertType.CONFIRMATION);
al.setTimeout(Alert.FOREVER) ;
display.setCurrent(al) ;
}
}
可以了,在運(yùn)行代碼,就會(huì)看到模擬同樣出現(xiàn)提示,但是確認(rèn)后,模擬器會(huì)走本地的網(wǎng)絡(luò),鏈接站點(diǎn)。




OK,成功在模擬器上訪問了。
注意,這僅僅是模擬器,部署到手機(jī)上,要對(duì)程序稍加改動(dòng),才能用。
在中國(guó)移動(dòng)提供的網(wǎng)絡(luò)連接中,分為CMNET和CMWAP兩種,其中CMNET可以無限制的訪問互聯(lián)網(wǎng)絡(luò),資費(fèi)比較貴。CMWAP類似一個(gè)HTTP的代碼,只能訪問支持HTTP的應(yīng)用,但是資費(fèi)便宜,穩(wěn)定性比較差。
在實(shí)際的J2ME網(wǎng)絡(luò)編程中,一般需要提供以CMWAP代理的方式連接網(wǎng)絡(luò),在J2ME中,連接的代碼和直接連接有所不同,代碼如下:
HttpConnection http = (HttpConnection)Connector.open(("http://10.0.0.172/"+url);
http.setRequestProperty("X-Online-Host",ServerName);
例如你需要訪問的地址為:http://www.test.com/login/loginServlet則上面的代碼就為:
HttpConnection http = (HttpConnection)Connector.open(("http://10.0.0.172/" + "login/loginServlet");
http.setRequestProperty("X-Online-Host","www.test.com");
在實(shí)際使用過程中,只需要使用實(shí)際需要訪問的地址的域名或者IP來代替ServerName,例如示例中的“www.test.com”,使用后續(xù)的地址類代替代碼中的url,例如示例中的“l(fā)ogin/loginServlet”,就可以實(shí)際的使用CMWAP代理來進(jìn)行連接了。
嗚呼,休息一下,在達(dá)內(nèi)學(xué)習(xí)完C++,最強(qiáng)大的多范型語言,學(xué)習(xí)J2ME只需要一周就足夠了。好比是九陽神功在體內(nèi),無所不能。阿,哈哈哈。Java乃是乾坤大挪移。