hellomobile

Hello Mobile

In the previous tutorial (Hello Core), we covered how a mobile client (in a mobile node) can communicate with a processing node in the SDDL core. In this tutorial, we will work with a different approach: communication between mobile nodes. This communication pass through the core, which act as a bridge connecting the nodes.

In this tutorial, our sample application will consist of two peer executing in mobile nodes: a sender and a receiver, as illustrated in the figure aside. The application code will be very similar to the first part, with the exception that the message need to be tagged with an identifier of the sender and receiver peers. The ID can be specified when the MRUDPNodeConnection connection is created. In addition, we will be sending a different object in the message, specifically a CustomData that encapsulate a serializable image with a string caption.

We start the tutorial explaining the CustomData structure that the node will send to the receiver. After that, we explain the changes we made in the mobile client applications. The tutorial start displaying the modifications that allow a peer HelloMobileSender to initiate the communication with a receiving one HelloMobileReceiver. The first one will send an image of Rio with the caption Rio de Janeiro. When the receiver get this message it replies with to the sender a string composed of Rio de Janeiro continua lindo!.

You do not need to copy the source code snippets shown in this tutorial. At the end of each section there is a link to download the entire node source code.

Applications can attach any kind of serializable object in their messages. In the previous tutorial HelloCore, we sent simple Strings. In this tutorial, we will send a custom application object. This object represents an Image with a Caption, for example, it can be a photo that the mobile node took on the fly and added a comment. The data encapsulate two other serializable attributes: an ImageIcon and a String, as shown in the below code. As a very simple test to check if our object was delivered correctly, we overwrite the toString function to print the metadata of the image alongside with the caption.

CustomData.java
package br.pucrio.inf.lac.helloworld;
 
import java.io.Serializable;
import javax.swing.ImageIcon;
 
public class CustomData implements Serializable {
  private static final long serialVersionUID = 6093226637618022646L;
  private String caption;
  private ImageIcon icon;
 
  public CustomData() {
  }
 
  public CustomData(String caption, String icon) {
    this.caption = caption;
 
    this.icon = new ImageIcon(Thread.currentThread().getContextClassLoader().getResource(icon));
  }
 
  public String getCaption() {
    return caption;
  }
 
  public ImageIcon getIcon() {
    return icon;
  }
 
  public void setCaption(String caption) {
    this.caption = caption;
  }
 
  public void setIcon(ImageIcon icon) {
    this.icon = icon;
  }
 
  @Override
  public String toString() {
    String firstPart  = "Caption: " + caption;
    String secondPart = "\nIcon Height: " + icon.getIconHeight();
    String thirdPart  = "\nIcon Width: " + icon.getIconWidth();
 
    return firstPart + secondPart + thirdPart;
  }
}

With very few modifications, exactly two, in the HelloCoreClient we can build our HelloMobileSender. Basically, we need to specify our and the targets node ID. This task is done using the UUID java class that represents global unique IDs. Applications can pass this ID as an argument for the MRUDPNodeConnection connection, if none is passed it automatically generates one. In addition to that, we now attach a CustomData object rather than a String one. The complete code of our Sender is shown below:

HelloMobileSender.java
package br.pucrio.inf.lac.helloworld;
 
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.List;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;
 
import lac.cnclib.net.NodeConnection;
import lac.cnclib.net.NodeConnectionListener;
import lac.cnclib.net.mrudp.MrUdpNodeConnection;
import lac.cnclib.sddl.message.ApplicationMessage;
import lac.cnclib.sddl.message.Message;
 
public class HelloMobileSender implements NodeConnectionListener {
 
  private static String       gatewayIP    = "127.0.0.1";
  private static int          gatewayPort  = 5500;
  private MrUdpNodeConnection connection;
  private UUID                myUUID;
 
  public HelloMobileSender() {
    myUUID = UUID.fromString("bb103877-8335-444a-be5f-db8d916f6754");
    InetSocketAddress address = new InetSocketAddress(gatewayIP, gatewayPort);
    try {
      connection = new MrUdpNodeConnection(myUUID);
      connection.addNodeConnectionListener(this);
      connection.connect(address);
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
 
  public static void main(String[] args) {
    Logger.getLogger("").setLevel(Level.ALL);
 
    HelloMobileSender sender = new HelloMobileSender();
    sender.sendPicture("Rio de Janeiro", "rio.jpg");
  }
 
  public void sendPicture(String caption, String imageName) {
      CustomData serializableContent = new CustomData(caption, imageName);
      ApplicationMessage message = new ApplicationMessage();
      message.setContentObject(serializableContent);
      message.setRecipientID(UUID.fromString("788b2b22-baa6-4c61-b1bb-01cff1f5f878"));
 
      try {
        System.out.println("Sending image + caption");
        connection.sendMessage(message);
      } catch (IOException e) {
        e.printStackTrace();
      }
  }
 
  public void connected(NodeConnection remoteCon) {
    ApplicationMessage message = new ApplicationMessage();
    message.setContentObject("Registering");
 
    try {
      connection.sendMessage(message);
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
 
  public void newMessageReceived(NodeConnection remoteCon, Message message) {
    System.out.println("Sender received the message!!");
    System.out.println(message.getContentObject());
  }
 
  public void reconnected(NodeConnection remoteCon, SocketAddress endPoint, boolean wasHandover, boolean wasMandatory) {}
 
  public void disconnected(NodeConnection remoteCon) {}
 
  public void unsentMessages(NodeConnection remoteCon, List<Message> unsentMessages) {}
 
  public void internalException(NodeConnection remoteCon, Exception e) {}
}

HelloMobileReceiver also has very few modifications from the mobile client application of the previous tutorial. In addition to specifying our ID, we send a message at connect so the middleware can associate our connection with our ID. The entire code of our application is displayed below:

HelloMobileReceiver.java
package br.pucrio.inf.lac.helloworld;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.List;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;
 
import lac.cnclib.net.NodeConnection;
import lac.cnclib.net.NodeConnectionListener;
import lac.cnclib.net.mrudp.MrUdpNodeConnection;
import lac.cnclib.sddl.message.ApplicationMessage;
import lac.cnclib.sddl.message.Message;
 
public class HelloMobileReceiver implements NodeConnectionListener {
 
  private static String       gatewayIP  = "127.0.0.1";
  private static int          gatewayPort  = 5500;
  private MrUdpNodeConnection connection;
  private UUID                myUUID;
 
  public HelloMobileReceiver() {
    myUUID = UUID.fromString("788b2b22-baa6-4c61-b1bb-01cff1f5f878");
    InetSocketAddress address = new InetSocketAddress(gatewayIP, gatewayPort);
    try {
      connection = new MrUdpNodeConnection(myUUID);
      connection.addNodeConnectionListener(this);
      connection.connect(address);
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
 
  public static void main(String[] args) {
    Logger.getLogger("").setLevel(Level.INFO);
 
    new HelloMobileReceiver();
  }
 
  public void connected(NodeConnection remoteCon) {
    ApplicationMessage message = new ApplicationMessage();
    message.setContentObject("Registering");
 
    try {
        connection.sendMessage(message);
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
 
  public void newMessageReceived(NodeConnection remoteCon, Message message) {
    System.out.println("Receiver Node!");
    System.out.println("Message: " + message.getContentObject());
 
    ApplicationMessage appMessage = new ApplicationMessage();
    appMessage.setContentObject("Rio de Janeiro continua lindo!");
    appMessage.setRecipientID(message.getSenderID());
 
    try {
      connection.sendMessage(appMessage);
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
 
  public void reconnected(NodeConnection remoteCon, SocketAddress endPoint, boolean wasHandover, boolean wasMandatory) {}
 
  public void disconnected(NodeConnection remoteCon) {}
 
  public void unsentMessages(NodeConnection remoteCon, List<Message> unsentMessages) {}
 
  public void internalException(NodeConnection remoteCon, Exception e) {}
}

The execution of our application is identical to the HelloCore example, if there is no gateway executing we need to create one to instantiate the core infrastructure. To do that, open a shell, and run the following command:

$ java -jar contextnet-2.5.jar 127.0.0.1 5500

After that, we instantiate the mobiles nodes. First run the HelloMobileReceiver class in Eclipse as a Java application. Finally, execute the HelloMobileSender class in Eclipse to start the mobile node application. You will see the printed messages in your console.

  • hellomobile.txt
  • Last modified: 2017/07/21 03:08
  • (external edit)