J2ME网络连接
在J2SE中可以使用java.net和java.io提供的类来访问网络服务和文件系统,由于移动信息设备的处理能力和内存的限制,它们并不适合运行在移动设备上。因此,J2ME定义了这些函数的子集,并提供了一套用于网络和文件访问的固定的程序包--- javax.microedition.io程序包。定义在javax.microedition.io类中的抽象网络和文件输入输出框架称为通用连接框架(GCF)。GCF定义了一套有关抽象化的内容来描述不同的通信方法。最高级的抽象被称作连接(Connection),还声明了六个接口(四个是直接的,两个是间接的)。这七个接口就构成了J2ME的CLDC的一部分,CLDC是大多数的能使用Java的无线设备使用的配置。设计这个配置的目的就是为所有的CLDC设备(手提电话,双向传呼机,低档的PDA等等)提供公用的网络和文件输入输出能力。虽然GCF的目的是公用网络和文件输入输出框架,但是生产商并不要求实现GCF中声明的所有的接口。有的厂家可以决定只支持socket连接,而其它的厂家可以选择只支持基于数据报的通信。为了促进跨越类似装置的可移植性,MIDP规范要求所有的MIDP设备实现HttpConnection接口。HttpConnection不是GCF的一部分,但是它是从GCF的一个接口ContentConnection衍生出来的。
在J2ME移动开发中,Java ME支持各种网络连接协议。它们都是基于通用连接框架(GCF)的有限连接设备配置(CLDC).
javax.microedition.io包为我们提供了以下协议的类和接口。
•Http Connection/ HTTPS Connenction
•UDP Connection
•TCP / IP Connection
•Comm Connection
这些协议可用于服务器的通信。
GCF通用连接框架的类与接口描述:
通用框架的类和接口 | 描述 |
Connector | 这个类是用于创建新的连接对象的工厂。 |
Connection | 这是最基本的通用的连接类型。 |
ContentConnection | 这个接口定义了流连接了哪些内容通过。 |
DatagramConnection | 这个接口定义了一个数据报连接必须具备的能力。 |
InputConnection | 这个接口定义了一个输入流连接必须具有的能力。 |
OutputConnection | 这个接口定义了一个输出流连接必须具备的能力。 |
StreamConnection | 这个接口定义了一个流连接必须具有的能力。 |
StreamConnectionNotifier | 这个接口定义了一个连接通知者必须具备的能力。 |
连接接口定义的7个基本类型的6个通讯:基本串行输入,基本串行输出,数据报的通信,通信插座,在一个客户端服务器通信的抽象通报机制,基本的HTTP与Web服务器通信。
这些接口之间的关系是图1所示:
使用公共的Connevtor类的静态方法open()可以创建连接方式的对象 。 如果成功,该方法返回一个对象,它实现连接的通用接口之一。 上面显示图是给这些接口在继承层次关系。 连接接口是所有这些连接的基接口。
使用Connector.open检索连接类对象,提供一个单一的String参数,指定一个协议,地址和参数:
try {
Connector.open("protocol:address;parameters");
} catch (ConnectionNotFoundExeption exe){
// handler is not available for socket connections
}
通过这个方法创建相关类型的连接协议。有几种可能的值的协议:file,socket,comm,datagram and http, File协议连接将使用file I/O流实现,comm协议连接使用串口通信实现,http表示连接是用于访问Web服务器创建的使用。
连接的目标可以是主机名,网络端口号,文件名或通信端口号。 parameters是可选的参数,它指定所需的附加信息来完成的连接字符串。
下面的例子说明了如何使用开放的方法来创建不同通信协议的基础上不同类型:
HTTP通信:
Connection httpConn= Connector.open(“http://www.google.com.hk”);
基于流的Socket通信:
Connection sc = Connector.open("socket://localhost:5555");
基于数据报套接字通信:
Connection sc = Connector.open("datagram://localhost:5555");
串口通讯:
Connection sc = Connector.open("comm: 0;baudrate=5555");
文件I / O
Connection ioStream=Connector.open("file://memorysdcard");
SocketConnection
接口定义的SocketConnection流套接字连接。 当你用它编写的MIDlet客户端,访问的TCP / IP的服务器,如下面的代码片断:
... // create a socket connection on port 5555 SocketConnection sc = (SocketConnection) Connector.open("socket://" + hostname + ":" + “5555”); //call setSocketOption to set other options sc.setSocketOption(DELAY, 0); sc.setSocketOption(KEEPALIVE, 0); //open input stream InputStream is = sc.openInputStream(); //open output stream OutputStream os = sc.openOutputStream(); // send data to server os.write("some string".getBytes()); // read stream data from server int ch = 0; while((ch = is.read()) != -1) { // do something with the response } // close all streams and connection is.close(); os.close(); sc.close(); ...
ServerSocketConnection
该ServerSocketConnection接口定义了服务器套接字流连接。 你使用它时,要求入站服务器的连接,如下面的片断:
...
// create a server to listen on port 5555
ServerSocketConnection serverConn = (ServerSocketConnection) Connector.open("socket://:5555");
// wait for a connection
SocketConnection sc = (SocketConnection) server.acceptAndOpen();
// call setSocketOption to set other options
sc.setSocketOption(DELAY, 0);
sc.setSocketOption(KEEPALIVE, 0);
//open data input stream
DataInputStream dataInput = client.openDataInputStream();
//open data output stream
DataOutputStream dataOutput = client.openDataOutputStream();
// read client data
String result = dataInput.readUTF();
// process request and send response
dataOutput.writeUTF(...);
// close all streams and connections
dataInput.close();
dataOutput.close();
sc.close();
serverConn.close();
...
HttpConnection
Java ME的处理httpconnections允许开发利用的HttpConnection类。 HTTP是一种request/response 协议。 客户端发起一个请求,使用一个统一资源定位符(URL)向服务器发送,并从服务器端获取相应。 这是一个网页浏览器和Web服务器一起工作。
打开一个连接后,您设置客户端请求的类型,指明HttpConnection.GET,HttpConnection.POST,或HttpConnection.HEAD请求方式之一:
不同请求的意义各不相同:
-
GET请求是用来请求数据的,如Web页面或者多媒体文件。你也可以通过URL用GET请求向服务器发送数据,不过用这种方式只可以发送少量的数据,很显然,嵌入到URL的数据是清晰易见的(plainly visible)。
-
POST请求可以通过单独的数据流来向URL发送数据。提交Web表单(form)会使你的浏览器向服务器发送POST请求。然后,Web服务器把检索到数据发送给页面或者URL指定的CGI程序中。在POST请求中你可以发送比GET请求更多的数据,不过它并不是真正安全可靠的,至少你的数据不是清晰的(in plain sight)。
-
最后要说说HEAD请求,它用来在服务器上检索元数据(metadata)。服务器的回应并不包含实际请求的数据,包含的只是关于请求的信息。
当收到客户端发出的请求后,服务器发出回应。回应信息可分为信息头和正文两个部分,它们包含实际请求的数据。信息头包括用来表示请求是否成功的状态字。状态字200表示请求成功,状态字400或者400以上表示请求失败。
HttpConnection hc = (HttpConnection)Connector.open(“http://samsung.com”);
hc.setRequestMethod(HttpConnection.GET);
该请求自动发送到您指定的网址并通过Connector.open打开。 通过getResponseCode()方法检查请求 HttpConnection 的是否成功。
If(hc.getResponseCode() == HttpConnection.HTTP_OK){
//if reaches here connection is success
}else{ //connection failed }
现在,打开该连接可以发送和接收就可以通过使用HttpConnection的openInputStream()和openOutputStream()方法打开接收相应的数据流对象。
MIDlet使用HttpConnection 从服务器读取数据例子:
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import javax.microedition.io.Connector;
import javax.microedition.io.HttpConnection;
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.StringItem;
import javax.microedition.midlet.MIDlet;
public class HttpMidlet extends MIDlet
implements CommandListener, Runnable
{
Display display;
Form form;
StringItem strItem;
Command cmdExit = new Command("Exit", 7, 1);
Command cmdFetch = new Command("Fetch", 4, 2);
public HttpMidlet() {
this.display = Display.getDisplay(this);
this.form = new Form("HttpConnection");
this.strItem = new StringItem("HTTP:", "Click Fetch to receive data");
this.form.append(this.strItem);
this.form.addCommand(this.cmdFetch);
this.form.addCommand(this.cmdExit);
this.form.setCommandListener(this);
}
public void startApp() {
this.display.setCurrent(this.form);
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
}
public void exitMIDlet() {
notifyDestroyed();
destroyApp(true);
}
public void commandAction(Command cmd, Displayable disp) {
if (cmd == this.cmdFetch) {
Thread thread = new Thread(this);
thread.start();
} else if (cmd == this.cmdExit) {
exitMIDlet();
}
}
public void run() {
getData();
}
public void getData() {
HttpConnection hc = null;
InputStream is = null;
try
{
hc = (HttpConnection)Connector.open("http://www.google.co.in");
this.strItem.setText("Fetching..");
hc.setRequestMethod("GET");
if (hc.getResponseCode() == 200)
{
is = hc.openInputStream(); //打开读取结果的输入流
int length = (int)hc.getLength();
String str;
String str;
if (length != -1) {
byte[] incomingData = new byte[length];
is.read(incomingData);
str = new String(incomingData);
} else {
ByteArrayOutputStream bytestream = new ByteArrayOutputStream();
while ((ch = is.read()) != -1)
{
int ch;
bytestream.write(ch);
}
str = new String(bytestream.toByteArray());
bytestream.close();
}
this.strItem.setText(str);
}
else
{
this.strItem.setText("unable to fetch data");
}
}
catch (Exception error)
{
exe.printStackTrace();
} finally {
if (is != null) {
try {
is.close();
} catch (Exception error) {
error.printStackTrace();
}
}
if (hc != null)
try {
hc.close();
} catch (Exception error) {
error.printStackTrace();
}
}
}
}