Skip to main content

By clicking Submit, you agree to the developerWorks terms of use.

The first time you sign into developerWorks, a profile is created for you. Select information in your profile (name, country/region, and company) is displayed to the public and will accompany any content you post. You may update your IBM account at any time.

All information submitted is secure.

  • Close [x]

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerworks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

By clicking Submit, you agree to the developerWorks terms of use.

All information submitted is secure.

  • Close [x]

Mobile P2P messaging, Part 2: Develop mobile extensions to generic P2P networks

Turn mobile devices into JXTA and Jabber clients

Michael Yuan (juntao@mail.utexas.edu), Research Associate, Center for Electronic Commerce, University of Texas at Austin
Michael J. Yuan is a PhD candidate at the University of Texas at Austin. He is the author of an upcoming Prentice Hall book, Java Mobile Enterprise Application Development. You can contact him at juntao@mail.utexas.edu.

Summary:  Generic peer-to-peer computing networks such as JXTA and Jabber are often too complex for mobile devices. Thus, lightweight mobile clients or special architectures that work through relays are needed to extend those P2P communities to mobile users. In this second part of our series on mobile peer-to-peer messaging, Michael Yuan discusses JXME, a J2ME JXTA client project. We'll examine the examples bundled in the JXME distribution to show you how to use the JXME APIs. In addition, we will also briefly discuss options to develop mobile Jabber applications.

Date:  01 Jan 2003
Level:  Intermediate
Also available in:   Korean

Activity:  14485 views
Comments:  

As we discussed in Part 1 of this series, SMS-based messaging is very convenient for wireless phone users. However, it is not a suitable messaging platform for non-phone mobile devices such as PDAs and WAN-connected handhelds. SMS messaging across different cell networks (such as international calls) can also be expensive or even in some cases impossible. In this second and final installment of our series on mobile P2P messaging, we will introduce you to two general-purpose peer-to-peer networks -- the JXTA P2P and Jabber instant messaging networks -- that you might use in situations that don't lend themselves to SMS. Materials in this article will also appear in my upcoming Prentice Hall book, Java Mobile Enterprise Application Development (see the Resources section below for a link).

The JXTA framework

JXTA defines a set of open protocols for peer-to-peer networks. These XML-based protocols describe complex operations such as peer discovery, endpoint routing, connection binding, basic query/response message exchange, and network propagation through rendezvous peers. To completely describe these protocols is beyond the scope of this article; interested readers should refer to the official JXTA Web site for more information or read some of the other developerWorks articles on the subject (see the Resources section below for links). To summarize, a JXTA network is made up of several components:

  • A peer is the basic element of any JXTA network. A peer implements core JXTA protocols, and operates independently of and asynchronously with all other peers. A peer provides application and/or network services and is capable of advertising itself.
  • A peer group is a collection of peers. JXTA defines the protocols that peers use to create, join, and monitor groups. A group provides services such as peer discovery, membership, access control, pipes, resolvers, and monitoring.
  • Pipes represent virtual connections among peers. A point-to-point pipe connects two peers; a propagate pipe connects a broadcast peer with multiple listeners. Pipe-connected peers are not necessarily directly physically linked; they can be connected through multiple intermediate pipes.
  • Messages are the data exchanged through pipes between peers and endpoints. JXTA defines an envelope format for all messages. Each peer can define its own message content format as long as that format conforms to the XML specification. However, in order for two peers to exchange meaningful information, they must understand each other's message format.
  • Advertisements are metadata structures for describing JXTA network resources. All peers and services understand advertisements.

JXTA is a generic P2P framework that goes far beyond simple messaging. It addresses issues like P2P file sharing, P2P application services, and collaborative distributed computing. While the JXTA protocols are designed to be independent of any implementation technology, JXTA's reference implementation is built on the Java platform. This reference implementation uses Java APIs to wrap JXTA protocol messages and provide a programmatic way to access the JXTA network from Java applications.


JXTA for mobile devices

The power and flexibility of JXTA come at a price: complexity. A JXTA peer needs to take care of a lot of tasks and process messages at the XML-over-socket level. Such a peer would be too complex to run on most mobile devices. In addition, neither XML nor raw socket support are part of the standard J2ME/MIDP specification. To make JXTA networks available to mobile P2P users, we need a set of lightweight JXTA APIs for mobile devices. The JXME project aims to provide JXTA APIs for the CLDC and MIDP platforms. It can also be used in higher-end J2ME profiles, such as the Personal Profile.

JXME uses relays to connect lightweight mobile peers to the rest of the JXTA network. The relays themselves are rendezvous JXTA peers that have full capabilities to handle pipes, advertisements, and peer group services. Mobile peers communicate with relays through binary-over-HTTP connections using messages conforming to the JXTA Binary Message format. Relays offer a number of peer services to mobile peers:

  • A relay filters out unnecessary advertisements, and strips down those advertisements that are sent in order to save bandwidth.
  • A relay routes (relays) messages to or from mobile peers.
  • A relay translates the relayed messages from JXTA XML format to JXTA Binary Message format, and vice versa, in order to enable interoperability between mobile peers and ordinary peers.
  • A relay acts as a proxy on behalf of its mobile peers. The relay interacts with other peers and pipes, and uses group services.

As developers, we do not need to worry about the exact format of the mobile-to-relay binary protocols and the exact implementation of relay peers. We just use the API classes provided by JXME.


Figure 1. JXME architecture
JXME architecture

The JXME API

You can check out the latest JXME source code -- both the relay and J2ME peer libraries -- from the project's public CVS server (see Resources). You can also download stable binary and source code from the JXME Web site.

Once you've downloaded the JXME package, you can start playing with the demos that come with it. Let's briefly walk through the steps to the run the demos using the Ant build script included in the download package. For a more detailed step-by-step tutorial, please refer to the JXME Web site.

First, you need to run the relay peer on a computer accessible from both your mobile device and your target JXTA community. The build.xml file in the proxy directory contains a runproxy task that will run a JXME relay. Make sure that you check the appropriate boxes to run it as Rendevous, relay and JxtaProxy. Now you can run JXME peers. The download package includes two sample JXME applications, chat and tictactoe, that you can experiment with.

Now, let's look into the JXME package itself. The JXME API only has three classes, all in the net.jxta.j2me package:

  • Element represents an element inside a JXTA message. An element contains a name, a namespace, a MIME type, and a binary array of data.
  • Message represents a JXTA message consisting of several elements. Message provides methods to access those elements.
  • PeerNetwork is the most useful class. It specifies the JXTA tasks that a mobile peer can perform through the relay. There are several useful methods in the PeerNetwork class:

    • createInstance() is a factory method that returns an instance of PeerNetwork with a specified peer name.
    • The connect() method connects to a relay at a specified HTTP URL. It returns a byte array of persistent state information; this information should be passed through the connect() method in all subsequent connections to the relay.
    • The create() method creates peers, groups, and pipes on the JXTA network through the relay proxy.
    • The search() method searches for peers, groups, and pipes.
    • The poll() method polls the relay for messages addressed to this mobile peer. It can be called iteratively in a server thread.
    • The listen() and close() methods open and close an input pipe, respectively.
    • The send() method sends a message to a specified pipe.

Figure 2. Classes in package net.jxta.j2me
Package net.jxta.j2me classes

An example

In this section, I will use a tutorial example -- mySend.java, which is included in the JXME source code package available from the JXME Web site -- to illustrate the usage of the API we outlined above. The JXME package consists of voluntary contributions made by many individuals to Project JXTA. The source code is licensed under the Sun Project JXTA Software License, which is based on the BSD license.

The example mobile peer running on a J2ME emulator performs a number of actions via a JXME relay running on the emulator's host PC (localhost) at port 9700. Of course, in real-world deployment, the mobile peer can run on any mobile device, and you can just change localhost to the IP address of your relay computer. The code for the JXME relay is included in the download package.

The example peer follows walks through a number of steps:

  1. It establishes a new pipe.
  2. It searches and finds the pipe it just established.
  3. It sends a message to itself through that pipe.
  4. It receives that message.

Let's look at the code for these steps. In Listing 1, the method peer.listen() instructs the relay to create a new pipe.


Listing 1. Creating a new pipe

// Create a peer and have it connect to the relay.
// A connection to relay is required before any other
// operations can be invoked.
String relayUrl = "http://localhost:9700/";
PeerNetwork peer = PeerNetwork.createInstance("mySendPeer");
byte [] persistentState = peer.connect(relayUrl, null);
 
// Have the peer create and open a Unicast pipe; PipeID will
// be returned asynchronously in a response message
int listenQueryId = peer.listen("myPipe", null, PeerNetwork.UNICAST_PIPE);
 
// Have peer search for this Pipe and then send it a Message
String pipeID = findMyPipe();
sendMyMessage(pipeID);
 
// Finally, have the peer poll for Messages sent to it
recvMessage();
}

After the pipe is created successfully, the relay generates a binary message to the mobile peer. The method findMyPipe() polls the relay in a loop until it receives this message indicating success. It then parses the message and gets the pipe ID. The binary message has an XML-like structure. Listing 2 demonstrates this process.


Listing 2. Getting the pipe we just created

public String findMyPipe() throws IOException {
  // Now poll for all messages addressed to us. Stop when we
  // find the response to our listen command
  int rid = -1;
  String id = null;
  String type = null;
  String name = null;
  String arg = null;
  String response = null;
 
  Message msg = null;
  while (true) {
    // do not use a timeout of 0, 0 means block forever
    msg = peer.poll(1);
    if (msg == null) {
      continue;
    }
    // look for a response to our search query
    for (int i = 0; i < msg.getElementCount(); i++ ) {
      Element e = msg.getElement(i);
      if (Message.PROXY_NAME_SPACE.equals(e.getNameSpace())) {
        String elementName = e.getName();
        if (Message.REQUESTID_TAG.equals(elementName)) {
          String rids = new String(e.getData());
          try {
            rid = Integer.parseInt(rids);
          } catch (NumberFormatException nfx) {
            System.err.println("Recvd invalid " +
                               Message.REQUESTID_TAG +
                               ": " + rids);
            continue;
          }
        } else if (Message.TYPE_TAG.equals(elementName)) {
          type = new String(e.getData());
        } else if (Message.NAME_TAG.equals(elementName)) {
          name = new String(e.getData());
        } else if (Message.ARG_TAG.equals(elementName)) {
          arg = new String(e.getData());
        } else if (Message.ID_TAG.equals(elementName)) {
          id = new String(e.getData());
        } else if (Message.RESPONSE_TAG.equals(elementName)) {
          response = new String(e.getData());
        }
      }
    }
    // PIPE_NAME: myPipe
    // PIPE_TYPE: PeerNetwork.UNICAST_PIPE
    if (rid == listenQueryId &&
        response.equals("success") &&
        type.equals("PIPE") &&
        name.equals(PIPE_NAME) &&
        arg.equals(PIPE_TYPE)) {
      return id;
    }
  }
}

In Listing 3, the method sendMyMessage() takes the pipe ID returned from the method findMyPipe() and sends a message through the pipe.


Listing 3. Sending a message through the pipe

public void sendMyMessage(String pipeID)
    throws IOException {
  Element[] elm = new Element[2];
  // Our Message will contain two elements. Receiver should look for
  // elements with the same names ("mySend:Name" and "mySend:Message")
  // PEER_NAME: mySendPeer
  elm[0] = new Element("mySend:Name", PEER_NAME.getBytes(),
                       null, null);
  elm[1] = new Element("mySend:Message", "Hello there".getBytes(),
                       null, null);
  Message msg = new Message(elm);
  // PIPE_NAME: myPipe
  // PIPE_TYPE: PeerNetwork.UNICAST_PIPE
  sendRequestId = peer.send(PIPE_NAME, pipeID, PIPE_TYPE, msg);
  System.out.println("send request id: " + sendRequestId);
}

As you'll recall, mySendPeer is itself listening to the pipe. Thus, the message we send above will be available to the same mobile peer from the relay. The method recvMessage() polls the relay until it receives the message, and then displays the message content once it has received it, as shown in Listing 4.


Listing 4. Receiving the message

public void recvMessage() throws IOException {
  Message msg = null;
  while (true) {
    msg = peer.poll(1);
    if (msg == null) {
      continue;
    }
    for (int i = 0; i < msg.getElementCount(); i++) {
      Element e = msg.getElement(i);
      if ("mySend".equals(e.getNameSpace()) &&
          "Name".equals(e.getName()))
        System.out.println("Message from: " +
                           new String(e.getData()));
      if ("mySend".equals(e.getNameSpace()) &&
          "Message".equals(e.getName()))
        System.out.println("Message: " +
                           new String(e.getData()));
    }
  }
}


Jabber instant messenger

Ultimately, the success of any P2P system depends on its ability to attract users. Although JXTA is a very powerful and technically advanced framework, its technical complexity hinders its adoption. Jabber is a much simpler P2P system than JXTA; it is primarily designed for instant messaging. Jabber has a much larger peer network than JXTA.

Jabber was originally designed to provide interoperability among popular Internet instant messaging systems (AOL, MSN, Yahoo!, ICQ, and so on). It is a powerful and flexible yet simple protocol that can wrap around all existing IM protocols. With powerful features and completely open XML protocols, Jabber is by far the most advanced IM system available today. Jabber can also support many advanced P2P applications, such as calendar groupware and file sharing.

Jabber peers communicate with each other through Jabber servers. Jabber servers can also talk with each other to form large domains of peers that are not directly connected to the same server. All communication among Jabber peers and servers takes the form of open XML-formatted messages sent over raw socket connections. (The specifications for these messages have been submitted to IETF.) As a result, Jabber servers and peers can be implemented independent of any platform. Jabber development libraries are available for the Java platform, C++, C#, Perl, Python, PHP, and even Flash.

The development of Jabber clients for J2ME devices, especially MIDP devices, is not trivial. Any MIDP Jabber client must bundle its own lightweight XML parser. In addition, the MIDP VM and underlying network must support raw socket connections. There are several MIDP 1.0-compatible Jabber clients or libraries available today:

  • Al Sutton's KVMJab is an open source Jabber library for the MIDP platform. It provides a simple API for developing MIDP Jabber applications. Although the source code is available, you have to donate to KVMJab development before you can incorporate it in your commercial software.
  • uppli's uMessenger is a fully featured Jabber IM client for MIDP. It also supports file sharing.

Conclusion

In this article, we discussed basic techniques and tools to extend JXTA and Jabber P2P networks to mobile peers. You should now be able to connect your mobile devices to large existing P2P communities through any TCP/IP-enabled wireless network.

After reading this series, you should understand why P2P is important to mobile applications, what P2P networks are available to mobile peers, and how to use J2ME tools to develop mobile P2P applications. Now you can add P2P features to your J2ME game or enterprise applications and get ready for the boom of mobile commerce in 2003!


Resources

About the author

Michael J. Yuan is a PhD candidate at the University of Texas at Austin. He is the author of an upcoming Prentice Hall book, Java Mobile Enterprise Application Development. You can contact him at juntao@mail.utexas.edu.

Report abuse help

Report abuse

Thank you. This entry has been flagged for moderator attention.


Report abuse help

Report abuse

Report abuse submission failed. Please try again later.


developerWorks: Sign in


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Select information in your profile (name, country/region, and company) is displayed to the public and will accompany any content you post. You may update your IBM account at any time.

Choose your display name

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


Rate this article

Comments

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Java technology
ArticleID=10741
ArticleTitle=Mobile P2P messaging, Part 2: Develop mobile extensions to generic P2P networks
publish-date=01012003
author1-email=juntao@mail.utexas.edu
author1-email-cc=