Você está na página 1de 12

J.E.D.I.

Chapter 06
Networking
In this section, we will be studying how to implement network-enabled MIDlets.
At the end of the lesson, the student should be able to:
Describe the Generic Connection Framework and how it can be used to support

different connection methods


Specify connection parameters using the GCF URL addressing format
Create HTTP/HTTPS connections
Create MIDlets using TCP sockets and UDP datagrams

6.1 The Generic Connection Framework


The Generic Connection Framework supports both packet-based (Sockets) and streambased (Datagrams) connections. As the name implies, this framework provides the basic
API for connections in CLDC. This framework provides a common foundation for
connections like HTTP, Sockets and Datagrams. Even Bluetooth and Serial I/O have a place
in this foundation. The GCF provides a generic and common set of API that abstracts all
types of connections. It should be noted that not all connection types are required to be
implemented by the MIDP devices.

6.1.1

The GCF Interface Hierarchy

Mobile Application Development

J.E.D.I.

Figure 1: GCF Interface Hierarchy


The extensible interface hierarchy of the GCF makes generalization possible. New
connection types may be added into this framework by extending this hierarchy.

6.1.2

The GCF Connection URL

Connection parameters are specified using a common addressing format:


scheme://username:password@host:port/path;parameters
1. scheme is the protocol or connection method. Example of scheme are: http, ftp, https
2. username is optional, but if specified, an @ must precede the host
3. password is optional and can only be specified if username is present. If password is
specified, it must be separated from the username by a colon (:)
4. host this parameter is required. This can be a hostname or a fully qualified domain
name (FQDN) or the IP address of the target host.
5. Port This parameter is optional. If not specified, the default port for the scheme will
be used.
6. Path
7. parameters this is optional, but must be preceded by a semi-colon when present
If we use square brackets to enclose optional parameters in this addressing format, we
can express it as:
scheme://[username[:password]@]host[:port]/path[;parameters]
The Uniform Resource Indicator (URI) as defined in RFC 2396 is the basis for this
addressing format.

Mobile Application Development

J.E.D.I.

In MIDP 2.0, only the "http" and "https" schemes are required to be implemented by the
device.

6.2 HTTP Connection


6.2.1

The HTTP Protocol

HTTP stands for HyperText Transfer Protocol. It is the protocol used to transfer web pages
from web servers (eg. www.sun.com) to web browsers. The client (web browser) requests
for a web page by specifying the path with the "GET" or "POST" commands.
For the "GET" method, parameters are specified and embedded on the URL. For example,
to pass a variable with a name "id" and value 100 to "index.jsp", the URL is specified as:
"http://hostname/index.jsp?id=100". Additional parameters are separated by an
ampersand (&), "http://hostname/index.jsp?id=100&page=2".
When the "POST" method is used, parameters are not part of the URL but are sent on
separate lines after the POST command.

Mobile Application Development

J.E.D.I.

Client / Web Browser

HTTP Server

GET /index.jsp?id=100 HTTP/1.1


HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Type: text/html;charset=ISO-8859-1
Date: Wed, 18 Jun 2005 14:09:31 GMT
Connection: close

<html>
<head>
<title>Test Page</title>
</head>
<body>
<h1 align="center">Test Page</h1>
</body>
</html>
Figure 2: Example of HTTP GET transaction

Mobile Application Development

J.E.D.I.

Client / Web Browser

HTTP Server

GET /non-existent.html HTTP/1.0


HTTP/1.1 404 /non-existent.html
Server: Apache-Coyote/1.1
Content-Type: text/html;charset=utf-8
Content-Length: 983
Date: Mon, 11 Jul 2005 13:21:01 GMT
Connection: close

<html><head><title>Apache Tomcat/5.5.7
Error report</title><style>...

<body><h1>HTTP Status 404</h1>


...
The requested resource (non-existent.html)
is not available.
...
</body></html>
Figure 3: Example of an HTTP GET transaction with an error response

6.2.2

Creating an HTTP Connection

You can open an HTTP connection by using Connector.open() and casting it with any one
of these three interfaces: StreamConnection, ContentConnection and HTTPConnection.
However, with the StreamConnection and ContentConnection, you cannot specify and
derive HTTP specific parameters and results.
When you use a StreamConnection, the length of the reply cannot be determined
beforehand. With a ContentConnection or an HTTPConnection, there is a way to determine
the length of the reply. But the length is not always available, so your program should be
able to fall back to other means of getting the reply without pre-knowledge of the content
length.
import javax.microedition.io.*;
HttpConnection connection = null;
InputStream iStream = null;
byte[] data = null;

try {
connection = (HttpConnection) Connector.open("http://www.sun.com/");
int code = connection.getResponseCode();

switch (code){

Mobile Application Development

J.E.D.I.

case HttpConnection.HTTP_OK:
iStream = connection.openInputStream();
int length = (int) connection.getLength();
if (length > 0){
data = new byte[length];
int totalBytes = 0;
int bytesRead = 0;
while ((totalBytes < length) && (bytesRead > 0)) {
bytesRead = iStream.read(
data, totalBytes, length - totalBytes);
if (bytesRead > 0){
totalBytes += bytesRead;
}
}
} else {
// length is not unknown, read per character
...
}
break;
default:
break;
}
...

6.2.3

Handling HTTP Redirects

Sometimes the server redirects the browser/client to another web page by replying with
HTTP_MOVED_PERM (301), HTTP_MOVED_TEMP (302), HTTP_SEE_OTHER (303) or
HTTP_TEMP_REDIRECT (307) instead of the usual HTTP_OK reply. Your program must be
able to detect this using getResponseCode(), get the new URI from the header using
getHeaderField( "Location" ), and retrieve the document from this new location.
int code = connection.getResponseCode();
switch(code){
case HttpConnection.HTTP_MOVED_PERM:
case HttpConnection.HTTP_MOVED_TEMP:
case HttpConnection.HTTP_SEE_OTHER:
case HttpConnection.HTTP_TEMP_REDIRECT:
String newUrl = conn.getHeaderField("Location");
...

Mobile Application Development

J.E.D.I.

6.3 HTTPS Connection


HTTPS is HTTP on top of a secure transport connection. Opening an HTTPS connection is
similar to opening an HTTP connection. Then only difference is the URL passed to
Connector.open() and casting the result to an HttpsConnection class variable.
An additional type of exception may also be thrown by Connector.open() aside from
IllegalArgumentException, ConnectionNotFoundException, java.io.IOException
and SecurityException. A CertificateException may be reported back caused by
certificate failures.

import javax.microedition.io.*;
HttpsConnection connection = null;
InputStream iStream = null;
byte[] data = null;

try {
connection = (HttpsConnection) Connector.open("https://www.sun.com/");
int code = connection.getResponseCode();
...
} catch (CertificateException ce){
switch (ce.getReason()){
case CertificateException.EXPIRED:
...
}
}

Mobile Application Development

J.E.D.I.

static byte BAD_EXTENSIONS


Indicates a certificate has unrecognized critical extensions.
static byte BROKEN_CHAIN
Indicates a certificate in a chain was not issued by the next
authority in the chain.
static byte CERTIFICATE_CHAIN_TOO_LONG
Indicates the server certificate chain exceeds the length allowed by
an issuer's policy.
static byte EXPIRED
Indicates a certificate is expired.
static byte INAPPROPRIATE_KEY_USAGE
Indicates a certificate public key has been used in way deemed
inappropriate by the issuer.
static byte MISSING_SIGNATURE
Indicates a certificate object does not contain a signature.
static byte NOT_YET_VALID
Indicates a certificate is not yet valid.
static byte ROOT_CA_EXPIRED
Indicates the root CA's public key is expired.
static byte SITENAME_MISMATCH
Indicates a certificate does not contain the correct site name.
static byte UNAUTHORIZED_INTERMEDIATE_CA
Indicates an intermediate certificate in the chain does not have the
authority to be a intermediate CA.
static byte UNRECOGNIZED_ISSUER
Indicates a certificate was issued by an unrecognized entity.
static byte UNSUPPORTED_PUBLIC_KEY_TYPE
Indicates that type of the public key in a certificate is not supported
by the device.
static byte UNSUPPORTED_SIGALG
Indicates a certificate was signed using an unsupported algorithm.
static byte VERIFICATION_FAILED
Indicates a certificate failed verification.
Figure 4: Reasons for a CertificateException
(excerpt from MIDP 2.0 Specification - JSR 118)

6.4 TCP Sockets


Most implementations of HTTP ride on top of the TCP layer. If you send data using the TCP
layer, it will be divided into smaller pieces called packets. The TCP layer guarantees that
all packets sent by the sender are received by the recipient, in the same order as it was
sent. If a packet was not received by the recipient, it would be resent. This means that
once you send a message, you can rest assured that it will be delivered to the recipient in

Mobile Application Development

J.E.D.I.

the same format as it was sent, with no omissions or insertions (barring any extreme
circumstances such as the recipient getting disconnected from the network).
The TCP layer handles packet reassembly and retransmission transparently. For example,
the HTTP protocol does not have to worry about packet disassembly and assembly because
this would be handled by the TCP layer.
Sometimes, the size of the message is too small and very inefficient to be delivered as a
single packet (packet overhead is very high compared to the payload). Imagine many
packets traversing the network with one byte payload and multi-byte overhead (say 16
bytes). This would make the network very inefficient as many packets flood the network
with only one byte of payload.
In these cases, the TCP implementation may wait for succeeding messages to be sent. It
would then pack as many messages as possible to a packet before sending the packet
away. If this happens, there would be additional lag or latency in the connection. If your
application requires that there should be as little latency as possible, you should set the
DELAY socket option to zero. Or, if your application can live with lost packets or unordered
packets, you may want to try a UDP or Datagram connection. UDP connections also uses
less packet overhead.

SocketConnection conn =
(SocketConnection) Connector.open("socket://www.sun.com:80");
client.setSocketOption(DELAY, 0);
InputStream iStream = conn.openInputStream();
OutputStream oStream = conn.openOutputStream();
os.write("GET / HTTP/1.0\n\n".getBytes());
int c = 0;
while((c = is.read()) != -1) {
// process the recieved data
...
}
iStream.close();
oStream.close();
conn.close();

6.5 Server Sockets


In the Client-Server model, the server continually waits for a connection from a client on
a certain agreed upon port number. We also use the Connector.open method to create a
server socket. The url passed to open() is of the same format as a TCP Socket, with the
hostname left blank (eg. socket://:8899).

ServerSocketConnection conn =
(ServerSocketConnection) Connector.open("socket://:8889");
// listen for a connection from a client
SocketConnection client = (SocketConnection) conn.acceptAndOpen();
client.setSocketOption(DELAY, 0);

Mobile Application Development

J.E.D.I.

InputStream iStream = client.openInputStream();


OutputStream oStream = client.openOutputStream();
// read/write to input/output streams
...
is.close();
os.close();
client.close();
server.close();

6.6 Datagrams
TCP Socket connections are reliable. In contrast, delivery of UDP packets are not
guaranteed. There is no guarantee that a packet sent using datagram connection would
be received by the peer. The order in which the packets are received is also unreliable.
The order in which packets are sent may not be the same order in which it will be received.
UDP Datagrams or packets are used when the application can operate even when a packet
is lost or packets are not delivered in order.

String url;
try {
if (isServer){
// start as server, listen at port 8888
url = "datagram://:8888";
} else {
// start as client, connect to port 8888 of host "localhost"
url = "datagram://localhost:8888";
}
dc = (DatagramConnection) Connector.open(url);

while (true) {
Datagram dgram = dc.newDatagram(128);
dc.receive(dgram);
if (isServer){
// started as server, get connection address
// for our message sending process
url = dgram.getAddress();
}
if (dgram.getLength() > 0){
String mesg =
new String(dgram.getData(), 0, dgram.getLength()));
}
}

Mobile Application Development

10

J.E.D.I.

}
catch (IOException ioe) {}
catch (Exception e) {}

...

private void sendMesg(String line){


try {
byte[] bytes = line.getBytes();
Datagram dgram = null;

dgram = dc.newDatagram(bytes, bytes.length, url);

dc.send(dgram);
} catch (Exception ioe) {}
}

6.7 Exercises
6.7.1

URL Fetcher

Create a MIDlet that prompts for an HTTP url. It would then fetch the url using the GET
method and display these connection/content properties (if available): Response Code,
Response Message, Length, Type, Encoding, Expiration and Last Modified Date.

Mobile Application Development

11

J.E.D.I.

Mobile Application Development

12

Você também pode gostar