UDP Datagram sample in J2ME

By: Fazal Viewed: 194 times  Printer Friendly Format    


MIDP differs somewhat from the J2SE platform in its support for datagram connections. J2SE has the java.net package. For instance, its DatagramPacket class defines a datagram. The DatagramSocket class implements a datagram protocol over a socket connection. These classes don't exist in CLDC/MIDP. In fact, there's no java.net package available in CLDC/MIDP. On the other hand, the CDC contains a robust java.net package that contains these classes.

The sample program below demonstrates the above concepts. It represents a datagram client that connects to a particular datagram service. The important steps that the program performs are as follows:

  1. It obtains a new DatagramConnection object.
  2. It gets a Datagram object from the DatagramConnection.
  3. It populates the Datagram with the properly formatted semantic information that
    comprises the request. (As the developer, ensure that the length of the datagram doesn't
    exceed the maximum length allowed by the protocol.)
  4. It receives a Datagram response from the DatagramConnection. This call blocks
    until a datagram is received or the call times out.
  5. It processes the data in the datagram.
  6. It repeats the cycle for ongoing communications.

The program doesn't actually implement Step 3. Doing so would require constructing a properly formatted message as expected by the service to which the client is connecting. Also, the "processing" of Step 5 simply involves printing the server's response to standard output. In a real application, the client would use the datagram information in some way for local processing.

/* Datagrams are sent and received by a datagram connection. This
program parses the payload of a received datagram and displays it on screen. */

import javax.microedition.midlet.MIDlet;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.TextBox;
import javax.microedition.lcdui.TextField;
import javax.microedition.io.Connector;
import javax.microedition.io.Datagram;
import javax.microedition.io.DatagramConnection;
import java.io.IOException;

/**
This class implements a datagram client that connects to
a Network Time Protocol (NTP) server on the NTP standard
port 123.
The client is designed to be controlled by a separate
thread, hence it implements Runnable. An application
can do communications asynchronously from its UI management.
Note that this file represents only a skeleton of a
complete client. The full semantics of the NTP service
messages are not shown here. The purpose is simply to
demonstrate the structure of a client using MIDP
datagrams.
*/

public class DatagramTest extends MIDlet
implements CommandListener, Runnable
{
private static final int BUF_SIZE = 1024;
private static Command exit = new Command("Exit", Command.EXIT, 1);
private static DatagramTest instance;
private Display display;
private TextBox dgramText;
// A datagram connection.
private DatagramConnection conn;
// A datagram which holds sent and received data.
private Datagram dgram;
// The address of the Network Time Protocol (NTP) daemon
// process on a particular server. NTP uses the UDP
// protocol.
private String address = "datagram://sr1-usca28-07:123";

/**
No-arg Constructor.
*/
public DatagramTest()
{
super();
instance = this;
}

/**
Constructor. Note no validity checks are made on the
parameter. If it is malformed, an exception will be
thrown when the connection is attempted.
@param service the URI of the datagram service to
which to connect.
*/
public DatagramTest(String service)
{
this();
address = service;
}
/**
Returns the single instance of this class. Calling
this method before constructing an object will return
a null pointer.
@return an instance of this class.
*/
public static DatagramTest getInstance()
{
return instance;
}
public void startApp()
{
display = Display.getDisplay(this);
dgramText = new TextBox("Datagram contents",
null,
2048,
TextField.ANY);
dgramText.setCommandListener(this);
display.setCurrent(dgramText);
run();
}

/**
Runs the datagram client. Opens a connection to the
datagram service. Populates a datagram object and
sends it. Receives the response synchronously, and
writes the bytes to standard output for demonstration
purposes. Catches any connection related excceptions
silently.
*/
public void run()
{
try
{
int maxLength;
// Open a client connection.
conn = (DatagramConnection)Connector.open(address);
maxLength = conn.getMaximumLength();
dgram = conn.newDatagram(maxLength);
// Ensure that the read/write pointer is at the
// beginning of the buffer, so data will overwrite
// any unitialized buffer memory.
dgram.reset();
// Populate the datagram before sending with a
// message that the datagram service understands.
// Construct the request in the datagram.
// ....
// Send the datagram just populated.
conn.send(dgram);
// Receive a datagram; its contents are put into
// the referenced datagram object.
conn.receive(dgram);
// Use this byte array to transfer the contents of
// the server's response to a more manageable Java
// object like a String. You can then use the
// datagram for another send or receive event.
byte[] data = dgram.getData();
// Extract the response string.
String str = new String(data);
// Do some processing with the response. Here
// just print it out for demonstration.
System.out.println(str);
// Reset the read/write pointer for the datagram
// object. The next time data is written into the
// datagram buffer, it will overwrite the data
// from the previous send or receive operation.
// This ensures that previous and next data are
// not mixed in the same buffer, and won't produce
// garbled messages.
dgram.reset();
// Continue processing, maybe sending and
// receiving more messages from the server.
// ....
}
catch (IOException ioe)
{
System.out.println(ioe.getMessage());
ioe.printStackTrace();
quit();
}
return;
}
public void pauseApp()
{
}
void quit()
{
destroyApp(true);
notifyDestroyed();
}
public void destroyApp(boolean destroy)
{
try
{
conn.close();
}
catch (IOException ioe)
{
ioe.printStackTrace();
}
}
public void display()
{
Display.getDisplay(this).setCurrent(dgramText);
}
public void commandAction(Command c, Displayable d)
{
if (c == exit)
{
quit();
}
}
}

Notice that any Datagram objects by default contain the same address as the DatagramConnection object that constructs them. You can change the address of a datagram using the methods in the Datagram interface.

The application must supply a Datagram object to send or receive a datagram. To send a datagram, the application populates the datagram object with data that constitutes the message to be sent to the server. When an application receives a datagram, its connection object populates the datagram object with the data it receives from the sender.

You can use the same datagram object to send and receive multiple messages. To do so, you must ensure that you don't mix data from different messages. Before reusing a datagram object to send or receive a new message, use the Datagram.reset() method to reset the read/write buffer pointer.

A Datagram object has a buffer that stores the bytes that comprise the message being sent or received. If you reuse a Datagram object, the bytes that were placed in the buffer from the previous send or receive operation are still there. Calling reset() sets the read/write offset pointer to point to the beginning of this buffer and sets the length to zero. Thus, you're effectively overwriting any previous data, ensuring that you are not mixing bytes from two separate messages.



Most Viewed Articles (in J2ME )

Latest Articles (in J2ME)

Comment on this tutorial