1. 定义 (摘自midp2.0 doc)
HTTP is a request-response protocol in which the parameters of request must be set before the request is sent . The connection exists in one of three states:
- Setup, in which the request parameters can be set
- Connected, in which request parameters have been sent and the response is expected
- Closed, the final state, in which the HTTP connection as been terminated
The following methods may be invoked only in the Setup state:
-
setRequestMethod
-
setRequestProperty
The transition from Setup to Connected is caused by any method that requires data to be sent to or received from the server.
The following methods cause the transition to the Connected state when the connection is in Setup state.
-
openInputStream
-
openDataInputStream
-
getLength
-
getType
-
getEncoding
-
getHeaderField
-
getResponseCode
-
getResponseMessage
-
getHeaderFieldInt
-
getHeaderFieldDate
-
getExpiration
-
getDate
-
getLastModified
-
getHeaderFieldKey
The following methods may be invoked while the connection is in Setup or Connected state.
-
close
-
getRequestMethod
-
getRequestProperty
-
getURL
-
getProtocol
-
getHost
-
getFile
-
getRef
-
getPort
-
getQuery
After an output stream has been opened by the openOutputStream
or openDataOutputStream
methods, attempts to change the request parameters via setRequestMethod
or the setRequestProperty
are ignored. Once the request parameters have been sent, these methods will throw an IOException
. When an output stream is closed via the OutputStream.close
or DataOutputStream.close
methods , the connection enters the Connected state. When the output stream is flushed via the OutputStream.flush
or DataOutputStream.flush
methods, the request parameters MUST be sent along with any data written to the stream.
The transition to Closed state from any other state is caused by the close
method and the closing all of the streams that were opened from the connection.
2. HTTP协议特点
(1) Http协议限制每次连接只处理一个请求。服务器处理完客户的请求并收到客户的应答后,即可断开连接 。由于Http是基于TCP/IP协议的,事实上它是面向连接的;
(2) Http协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传 ,这样可能导致每次连接传送的数据量增大。Http协议的无状态特性为我们开发IM之类的软件增加了困难,客户端必须不停地轮循服务器以获得最新数据。
(3) Http支持Client-Server模式 ,每一个信息交换分为四 步:建立连接、发送请求信息、发送响应信息、关闭连接,这四步的划分是由于Http协议是基于请求/响应模式的 ;
(4) Http允许传输任意类型的数据对象。正在传输的类型由Content-Type加以标记 ,eg:txt文件的 Content-Type = "text/plain"; 当Client向Server请求服务时,Http协议只需传送请求方法(GET/POST/HEAD)和路径即可。
3. MIDP规范支持HTTP协议的子集 ,规范中没有要求必须使用基于IP的网络来实现HTTP协议支持,如TCP/IP。MIDP允许HTTP实现使用非IP协议,如WAP,非IP协议则需要一个网关作为代理来访问Internet上的服务器。
4. 网络地址转换
当移动电话访问位于公网上的服务器时,运营商会为移动电话分配一个IP地址。一般来说,他们分配的地址是动态IP地址(用动态主机配置协议Dynamic Host Configuration Protocol, DHCP分配)。但这些地址无法从公网上直接访问,因此需要一台网络地址转换(Network Address Translation, NAT)网关来执行电话IP地址与公共IP地址之间的映射。
每当电话发起对互联网的UDP或TCP连接时,NAT网关都会创建一个映射,把该电话的IP地址和端口号映射到网关自己的IP地址和一个新端口号。互联网主机会把这个IP地址和端口号看做是TCP连接或UDP数据报的原始地址和端口,并把答复信息发送到这个原始地址和端口。然后,该NAT网关再将其映射回电话的IP地址和端口号,并将答复信息转发给电话。因此,从Web服务器日志上看到的IP地址并非手机的IP地址,而是网关的地址。
运营商的NAT网关也会不断跟踪与该映射相关的服务器,并拒绝来自其他服务器指向该映射的“响应”。这是一种有用的防火墙功能,因为NAT网关的IP地址是众所周知的,其端口号也很容易被猜到,如果没有这种防火墙功能,攻击者就能将数据包发送给那些没有请求过的电话。
这种网络地址转换方案造成两个移动电话之间无法通过TCP或UDP进行点对点的连接。当在移动网络上使用HTTP、TCP、UDP等协议时,各个电话一定需要通过一台互联网服务器,但它们之间并不能直接通信。
5. Demo
(1) Read the HTTP headers and the data using HttpConnection
Connector.open is used to open url and a HttpConnection is returned. The HTTP headers are read and processed. If the length is available, it is used to read the data in bulk. From the HttpConnection the InputStream is opened. It is used to read every character until end of file (-1) . If an exception is thrown the connection and stream are closed.
private void getViaHttpConnection(String url) throws IOException {
HttpConnection c = null;
InputStream is = null;
int rc;
try {
c = (HttpConnection) Connector.open(url);
/**
* Getting the response code will open the connection,
* send the request, and read the HTTP response headers.
* The headers are stored until requested.
*/
rc = c.getResponseCode();
if (rc != HttpConnection.HTTP_OK) {
throw new IOException("Http response code: " + rc);
}
is = c.openInputStream();
// Get the ContentType
String type = c.getType();
// Get the length and process the data
int len = (int) c.getLength();
if (len > 0) {
int actual = 0;
int bytesread = 0;
byte[] data = new byte[len];
while ((bytesread != len) && (actual != -1)) {
// the total number of bytes read into the buffer, or -1 if there is no more data because the end of the stream has been reached.
actual = is.read(data, bytesread, len - bytesread);
bytesread += actual;
}
} else {
int ch;
while ((ch = is.read()) != -1) {
// ...
}
}
} catch (ClassCastException e) {
throw new IllegalArgumentException("Not an Http URL");
} finally {
if (is != null) is.close();
if (c != null) c.close();
}
}
(2)Post a request with some headers and content to the server and process the headers and content
The request method is set to POST and request headers set. A simple command is written and flushed. The HTTP headers are read and processed. If the length is available, it is used to read the data in bulk. From the HttpConnection the InputStream is opened. It is used to read every character until end of file (-1) . If an exception is thrown the connection and stream is closed.
private void postViaHttpConnection(String url) throws IOException {
HttpConnection c = null;
InputStream is = null;
OutputStream os = null;
int rc;
try {
c = (HttpConnection) Connector.open(url);
// Set the request method and headers
c.setRequestMethod(HttpConnection.POST);
c.setRequestProperty("If-Modified-Since", "29 Oct 1999 19:43:31 GMT");
c.setRequestProperty("Content-Language", "en-US");
// Getting the output stream may flush the headers
os = c.openOutputStream();
os.write("Forrest.He".getBytes());
os.flush(); // Optional, getResponseCode will flush
/**
* Getting the response code will open the connection,
* send the request, and read the Http response headers.
* The headers are stored until requested.
*/
rc = c.getResponseCode();
if (rc != HttpConnection.HTTP_OK) {
throw new IOException("HTTP response code: " + rc);
}
is = c.openInputStream();
// ... 同getViaHttpConnection()
} catch (ClassCastException e) {
} finally {
}
}
aa