hellogroup

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

hellogroup [2013/09/25 13:58]
mroriz [HelloGroupDefinerClient]
hellogroup [2017/07/21 03:08]
Line 1: Line 1:
-====== HelloGroup ====== 
-{{ :hellogroupext.png?nolink&400|}} 
-In this tutorial we will exemplify SDDL's group communication capabilities. In particular, we will show how mobile clients can join a group and communicate through it. Similarly to one-to-one (unicast) communication (see Tutorial [[HelloMobile]]), also group communication is asynchronous, which means that message delivery is based on callback method invocation. 
- 
-Our sample application will consist of two peer executing in mobile nodes: a group peer that will act as a client and another that act as a receiver, as illustrated in the figure aside. The application code share much similarity with the previous tutorials, with the addition that now the nodes implement the ''GroupMembershipListener'', that trigger events for joining, leaving, and receiving messages from Groups. 
- 
-We start the tutorial explaining the concept of Groups, that in SDDL can be explicit or implicit. After that, we explain the changes we made in the mobile client applications to accommodate those concepts. The tutorial then displayis the the modifications that allow a peer ''HelloGroupClient'' to explicity join a Group and send a message to it. The ''HelloGroupPeer'' peer will join this group to receive the message sent. After this example, we show an implicit group communication, which requires a mobile node application and a processing node ''GroupDefiner'' to map nodes to groups. 
- 
-<WRAP tip> 
-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. Moreover, all examples are included in the virtual machine made available. 
-</WRAP> 
- 
-===== Group Concept ===== 
-In SDDL, groups are created/defined according to the group selection logic implemented in the ''GroupDefiner'', and mobile clients can only become members of (any set of) existing groups. Group membership means that the mobile client will receive all the messages posted to its group. A mobile client may become member of any group in any of following two ways: 
-  - Implicit: Some of its application message attribute satisfies the membership condition in the group selection logic. For example, its ''UUID'' is included in a static set of group member IDs, or otherwise, its geographic coordinate falls inside a specific region boundary;  
-  - Explicit: The mobile client explicitly joins an existing group through the ''join()'' operation of the [[ClientLib]] GroupAPI. 
- 
-It is worth noting that membership is the conjunction of the implicit and the explicit case: i.e., a mobile client which is an implicit member of a group (case 1) will remain so even after making the leave() operation, and a client that is not an implicit member of a group, can control its group membership through the ''join()'' and ''leave()'' operations of the GroupAPI. 
- 
-Moreover, in SDDL groups are open. This means that regarding the sending of groupcast messages there is no need to be a group member. Instead, it is sufficient to use the correct ''GroupID'' as the message destination.  
- 
-===== HelloGroupClient ===== 
-The ''HelloGroupClient'' application adds some modifications to the previous clients. Our client now specify a group that we want to join and communicate with it. In SDDL, each group is identified by its type and id, precisely, an integer pair. In our sample application, we want to communicate with the group that has group type of ''250'' and id of ''300'' 
- 
-To communicate with groups using the ''GroupAPI'', we need to instantiate a group manager in a node <=> gateway connection. This is done usually in the connection event function that is triggered when the node connects to the gateway.  After that, we execute a join call in the manager passing the group that we want to communicate as parameter. After that, we can send messages to the group members (groupcast messages) using the group manager. Finally, we added a code in our ''newMessageReceived'' method to exemplify that sending to the group, all nodes receives the message, including the sender. The code is shown below: 
- 
-<file java HelloGroupClient.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.logging.Level; 
-import java.util.logging.Logger; 
- 
-import lac.cnclib.net.NodeConnection; 
-import lac.cnclib.net.NodeConnectionListener; 
-import lac.cnclib.net.groups.Group; 
-import lac.cnclib.net.groups.GroupCommunicationManager; 
-import lac.cnclib.net.groups.GroupMembershipListener; 
-import lac.cnclib.net.mrudp.MrUdpNodeConnection; 
-import lac.cnclib.sddl.message.ApplicationMessage; 
-import lac.cnclib.sddl.message.Message; 
- 
-public class HelloGroupClient implements NodeConnectionListener, GroupMembershipListener { 
- 
-  private static String               gatewayIP    = "127.0.0.1"; 
-  private static int                  gatewayPort  = 5500; 
-  private GroupCommunicationManager   groupManager; 
-  private Group                       aGroup; 
- 
-  public HelloGroupClient() { 
-    InetSocketAddress address = new InetSocketAddress(gatewayIP, gatewayPort); 
-    try { 
-      MrUdpNodeConnection connection = new MrUdpNodeConnection(); 
-      connection.connect(address); 
-      connection.addNodeConnectionListener(this); 
- 
-      aGroup = new Group(250, 300); 
-    } catch (IOException e) { 
-      e.printStackTrace(); 
-    } 
-  } 
- 
-  public static void main(String[] args) { 
-    Logger.getLogger("").setLevel(Level.OFF); 
- 
-    new HelloGroupClient(); 
-  } 
- 
-  @Override 
-  public void connected(NodeConnection remoteCon) { 
-    groupManager = new GroupCommunicationManager(remoteCon); 
-    groupManager.addMembershipListener(this); 
- 
-    try { 
-      groupManager.joinGroup(aGroup); 
- 
-      ApplicationMessage appMsg = new ApplicationMessage(); 
-      appMsg.setContentObject("Group Message"); 
- 
-      groupManager.sendGroupcastMessage(appMsg, aGroup); 
-    } catch (IOException e) { 
-      e.printStackTrace(); 
-    } 
-  } 
- 
-  @Override 
-  public void reconnected(NodeConnection remoteCon, SocketAddress endPoint, boolean wasHandover, boolean wasMandatory) {} 
- 
-  @Override 
-  public void disconnected(NodeConnection remoteCon) {} 
- 
-  @Override 
-  public void newMessageReceived(NodeConnection remoteCon, Message message) { 
-    System.out.println("Group sender also received: " + message.getContentObject()); 
-  } 
- 
-  @Override 
-  public void unsentMessages(NodeConnection remoteCon, List<Message> unsentMessages) {} 
- 
-  @Override 
-  public void internalException(NodeConnection remoteCon, Exception e) {} 
- 
-  @Override 
-  public void enteringGroups(List<Group> groups) { 
-    System.out.println("Entered in the group"); 
-  } 
- 
-  @Override 
-  public void leavingGroups(List<Group> groups) {} 
-} 
-</file> 
- 
-===== HelloGroupPeer ===== 
-Since group clients and peers are identical, the ''HelloGroupPeer'' receiver code is pretty much the same. With the exception that this client does not send the message, only receives. The complete code is below: 
- 
-<file java HelloGroupPeer.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.logging.Level; 
-import java.util.logging.Logger; 
- 
-import lac.cnclib.net.NodeConnection; 
-import lac.cnclib.net.NodeConnectionListener; 
-import lac.cnclib.net.groups.Group; 
-import lac.cnclib.net.groups.GroupCommunicationManager; 
-import lac.cnclib.net.groups.GroupMembershipListener; 
-import lac.cnclib.net.mrudp.MrUdpNodeConnection; 
-import lac.cnclib.sddl.message.Message; 
- 
-public class HelloGroupPeer implements NodeConnectionListener, GroupMembershipListener { 
- 
-  private static String              gatewayIP    = "127.0.0.1"; 
-  private static int                 gatewayPort  = 5500; 
-  private GroupCommunicationManager  groupManager; 
-  private Group                      aGroup; 
- 
-  public HelloGroupPeer() { 
-    InetSocketAddress address = new InetSocketAddress(gatewayIP, gatewayPort); 
-    try { 
-      MrUdpNodeConnection connection = new MrUdpNodeConnection(); 
-      connection.connect(address); 
-      connection.addNodeConnectionListener(this); 
- 
-      aGroup = new Group(250, 300); 
-    } catch (IOException e) { 
-      e.printStackTrace(); 
-    } 
-  } 
- 
-  public static void main(String[] args) { 
-    Logger.getLogger("").setLevel(Level.OFF); 
- 
-    new HelloGroupPeer(); 
-  } 
- 
-  @Override 
-  public void connected(NodeConnection remoteCon) { 
-    groupManager = new GroupCommunicationManager(remoteCon); 
-    groupManager.addMembershipListener(this); 
- 
-    try { 
-      groupManager.joinGroup(aGroup); 
-    } catch (IOException e) { 
-      e.printStackTrace(); 
-    } 
-  } 
- 
-  @Override 
-  public void reconnected(NodeConnection remoteCon, SocketAddress endPoint, boolean wasHandover, boolean wasMandatory) {} 
- 
-  @Override 
-  public void disconnected(NodeConnection remoteCon) {} 
- 
-  @Override 
-  public void newMessageReceived(NodeConnection remoteCon, Message message) { 
-    System.out.println("Group Peer received: " + message.getContentObject()); 
-  } 
- 
-  @Override 
-  public void unsentMessages(NodeConnection remoteCon, List<Message> unsentMessages) {} 
- 
-  @Override 
-  public void internalException(NodeConnection remoteCon, Exception e) {} 
- 
-  @Override 
-  public void enteringGroups(List<Group> groups) { 
-    System.out.println("Entered in the group"); 
-  } 
- 
-  @Override 
-  public void leavingGroups(List<Group> groups) {} 
-} 
-</file> 
- 
-===== HelloGroupExecution ===== 
-The execution of our application is identical to the others 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: 
- 
-  $ gateway 127.0.0.1 5500 
- 
-After that, we instantiate the mobiles nodes. First run the ''HelloGroupPeer'' class in Eclipse as a Java application. Finally, execute the ''HelloGroupClient'' class in Eclipse to start the mobile node application. You will see the printed messages in your console. 
- 
-===== GroupDefiner ===== 
-The GroupDefiner concept allows applications to implicitly aggregate nodes in groups. When used, the SDDL core redirect the mobile nodes messages to the GroupDefiner, that apply some application logic, which returns the group set of that node. To exercise this concept, in this tutorial, we are developing a simple logic that separates the nodes based in their identifier UUID. If their UUID least significant bits is even they are assigned to group 2, otherwise (it is odd) they are assigned to group 3. By default we also associate them to our application default group, which we consider to be group 1. In addition, every GroupDefiner only process information of a given group type. Therefore, every GroupDefiner must implement the ''GroupSelector'' interface, which contains two methods:  
-  * ''getGroupType()'' - which returns the definer group type 
-  * ''processGroup(Message message)'' - which classify and returns the node’s group ID 
-  
-The entire code of our GroupDefiner and GroupSelector is listed below: 
-<file java HelloGroupSelector.java> 
-package br.pucrio.inf.lac.helloworld; 
- 
-import java.util.HashSet; 
-import java.util.Set; 
- 
-import lac.cnet.groupdefiner.components.groupselector.GroupSelector; 
-import lac.cnet.sddl.objects.Message; 
- 
-public class HelloGroupSelector implements GroupSelector { 
- 
-  @Override 
-  public int getGroupType() { 
-    return 3; 
-  } 
- 
-  @Override 
-  public Set<Integer> processGroups(Message nodeMessage) { 
-    System.out.println("STARTED CLASSIFYING GROUP MESSAGE"); 
- 
-    // Add the node to two groups 
-    HashSet<Integer> groupCollection = new HashSet<Integer>(2, 1); 
- 
-    // Some default group (ID = 1) 
-    groupCollection.add(1); 
- 
-    // Even (2) or Odd Group (3) 
-    if (nodeMessage.getSenderId().getLeastSignificantBits() % 2 == 0) { 
-      groupCollection.add(2); 
-    } else { 
-      groupCollection.add(3); 
-    } 
- 
-    System.out.println("ENDED CLASSIFYING GROUP MESSAGE\n"); 
-    return groupCollection; 
-  } 
-} 
-</file> 
- 
-<file java HelloGroupDefiner.java> 
-package br.pucrio.inf.lac.helloworld; 
- 
-import lac.cnet.groupdefiner.components.GroupDefiner; 
-import lac.cnet.groupdefiner.components.groupselector.GroupSelector; 
- 
-public class HelloGroupDefiner { 
- 
-  public static void main(String[] args) { 
- 
-    GroupSelector groupSelector = new HelloGroupSelector(); 
-    new GroupDefiner(groupSelector); 
- 
-    try { 
-      Thread.sleep(Long.MAX_VALUE); 
-    } catch (InterruptedException e) { 
-      e.printStackTrace(); 
-    } 
-  } 
- 
-} 
-</file> 
-===== HelloGroupReceiver ===== 
-To test our GroupDefiner, we will implement two mobile nodes receiver. One will have its UUID least significant bit as an even number, while the other one has an odd one. They will respectively be classified in the groups ID ''<1, 2>'' and ''<1, 3>'' of group type ''3''. Each node will send a simple message just so the definer can classify them. After that, each node waits for the messages from their implicit group. The code of both mobile node receivers are below. Note, that the only difference is the line where the UUID is generated. We enforce that the number is even or odd accordingly to the given node. 
- 
-<file java HelloGroupDefinerEvenReceiver.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.groups.Group; 
-import lac.cnclib.net.groups.GroupCommunicationManager; 
-import lac.cnclib.net.groups.GroupMembershipListener; 
-import lac.cnclib.net.mrudp.MrUdpNodeConnection; 
-import lac.cnclib.sddl.message.ApplicationMessage; 
-import lac.cnclib.sddl.message.Message; 
- 
-public class HelloGroupDefinerEvenReceiver implements NodeConnectionListener, GroupMembershipListener { 
-  private final static String        gatewayIP    = "127.0.0.1"; 
-  private final static int           gatewayPort  = 5500; 
-  private GroupCommunicationManager  groupManager; 
- 
-  public HelloGroupDefinerEvenReceiver() { 
-    UUID uuid = UUID.randomUUID(); 
- 
-    while (uuid.getLeastSignificantBits() % 2 != 0) { 
-      uuid = UUID.randomUUID(); 
-    } 
-    InetSocketAddress address = new InetSocketAddress(gatewayIP, gatewayPort); 
-    try { 
-      MrUdpNodeConnection connection = new MrUdpNodeConnection(uuid); 
-      connection.connect(address); 
-      connection.addNodeConnectionListener(this); 
-    } catch (IOException e) { 
-      e.printStackTrace(); 
-    } 
-  } 
- 
-  public static void main(String[] args) { 
-    Logger.getLogger("").setLevel(Level.OFF); 
-    new HelloGroupDefinerEvenReceiver(); 
-  } 
- 
-  @Override 
-  public void connected(NodeConnection remoteCon) { 
-    groupManager = new GroupCommunicationManager(remoteCon); 
-    groupManager.addMembershipListener(this); 
- 
-    try { 
-      ApplicationMessage message = new ApplicationMessage(); 
-      String serializableContent = "Bogus Message for Group Definer"; 
-      message.setContentObject(serializableContent); 
-       
-      remoteCon.sendMessage(message); 
-    } catch (Exception e) { 
-      e.printStackTrace(); 
-    } 
-  } 
- 
-  @Override 
-  public void reconnected(NodeConnection remoteCon, SocketAddress endPoint, boolean wasHandover, boolean wasMandatory) {} 
- 
-  @Override 
-  public void disconnected(NodeConnection remoteCon) {} 
- 
-  @Override 
-  public void newMessageReceived(NodeConnection remoteCon, Message message) { 
-    System.out.println(message.getContentObject()); 
-  } 
- 
-  @Override 
-  public void unsentMessages(NodeConnection remoteCon, List<Message> unsentMessages) {} 
- 
-  @Override 
-  public void internalException(NodeConnection remoteCon, Exception e) {} 
- 
-  @Override 
-  public void enteringGroups(List<Group> groups) {} 
- 
-  @Override 
-  public void leavingGroups(List<Group> groups) {} 
-} 
-</file> 
- 
-<file java HelloGroupDefinerOddReceiver.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.groups.Group; 
-import lac.cnclib.net.groups.GroupCommunicationManager; 
-import lac.cnclib.net.groups.GroupMembershipListener; 
-import lac.cnclib.net.mrudp.MrUdpNodeConnection; 
-import lac.cnclib.sddl.message.ApplicationMessage; 
-import lac.cnclib.sddl.message.Message; 
- 
-public class HelloGroupDefinerOddReceiver implements NodeConnectionListener, GroupMembershipListener { 
-  private final static String        gatewayIP    = "127.0.0.1"; 
-  private final static int           gatewayPort  = 5500; 
-  private GroupCommunicationManager  groupManager; 
- 
-  public HelloGroupDefinerOddReceiver() { 
-    UUID uuid = UUID.randomUUID(); 
- 
-    while (uuid.getLeastSignificantBits() % 2 == 0) { 
-      uuid = UUID.randomUUID(); 
-    } 
-    InetSocketAddress address = new InetSocketAddress(gatewayIP, gatewayPort); 
-    try { 
-      MrUdpNodeConnection connection = new MrUdpNodeConnection(uuid); 
-      connection.connect(address); 
-      connection.addNodeConnectionListener(this); 
-    } catch (IOException e) { 
-      e.printStackTrace(); 
-    } 
-  } 
- 
-  public static void main(String[] args) { 
-    Logger.getLogger("").setLevel(Level.OFF); 
-    new HelloGroupDefinerOddReceiver(); 
-  } 
- 
-  @Override 
-  public void connected(NodeConnection remoteCon) { 
-    groupManager = new GroupCommunicationManager(remoteCon); 
-    groupManager.addMembershipListener(this); 
- 
-    try { 
-      ApplicationMessage message = new ApplicationMessage(); 
-      String serializableContent = "Bogus Message for Group Definer"; 
-      message.setContentObject(serializableContent); 
-       
-      remoteCon.sendMessage(message); 
-    } catch (Exception e) { 
-      e.printStackTrace(); 
-    } 
-  } 
- 
-  @Override 
-  public void reconnected(NodeConnection remoteCon, SocketAddress endPoint, boolean wasHandover, boolean wasMandatory) {} 
- 
-  @Override 
-  public void disconnected(NodeConnection remoteCon) {} 
- 
-  @Override 
-  public void newMessageReceived(NodeConnection remoteCon, Message message) { 
-    System.out.println(message.getContentObject()); 
-  } 
- 
-  @Override 
-  public void unsentMessages(NodeConnection remoteCon, List<Message> unsentMessages) {} 
- 
-  @Override 
-  public void internalException(NodeConnection remoteCon, Exception e) {} 
- 
-  @Override 
-  public void enteringGroups(List<Group> groups) {} 
- 
-  @Override 
-  public void leavingGroups(List<Group> groups) {} 
-} 
-</file> 
- 
-===== HelloGroupDefinerClient ===== 
- 
-Our client will act slightly the same as the ''HelloGroupClient''. With the difference, that we now send messages to the group type 3, and groups ID 1, 2, and 3. The ''HelloGroupDefinerEvenReceiver'' will receives the messages of group ID 1 and 2, while the ''HelloGroupDefinerOddReceiver'' will receives the messages of groups ID 1 and 3. The complete code of our client is shown below: 
- 
-<file java HelloGroupClient.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.logging.Level; 
-import java.util.logging.Logger; 
- 
-import lac.cnclib.net.NodeConnection; 
-import lac.cnclib.net.NodeConnectionListener; 
-import lac.cnclib.net.groups.Group; 
-import lac.cnclib.net.groups.GroupCommunicationManager; 
-import lac.cnclib.net.groups.GroupMembershipListener; 
-import lac.cnclib.net.mrudp.MrUdpNodeConnection; 
-import lac.cnclib.sddl.message.ApplicationMessage; 
-import lac.cnclib.sddl.message.Message; 
- 
-public class HelloGroupClient implements NodeConnectionListener, GroupMembershipListener { 
- 
-  private final static String        gatewayIP    = "127.0.0.1"; 
-  private final static int           gatewayPort  = 5500; 
-  private GroupCommunicationManager  groupManager; 
- 
-  public HelloGroupClient() { 
-    InetSocketAddress address = new InetSocketAddress(gatewayIP, gatewayPort); 
-    try { 
-      MrUdpNodeConnection connection = new MrUdpNodeConnection(); 
-      connection.connect(address); 
-      connection.addNodeConnectionListener(this); 
- 
-      try { 
-        Thread.sleep(30000); 
-      } catch (InterruptedException e) { 
-        e.printStackTrace(); 
-      } 
-    } catch (IOException e) { 
-      e.printStackTrace(); 
-    } 
-  } 
- 
-  public static void main(String[] args) { 
-    Logger.getLogger("").setLevel(Level.OFF); 
- 
-    new HelloGroupClient(); 
-  } 
- 
-  @Override 
-  public void connected(NodeConnection remoteCon) { 
-    groupManager = new GroupCommunicationManager(remoteCon); 
-    groupManager.addMembershipListener(this); 
- 
-    try { 
-      // i = 1 Default 
-      // i = 2 EVEN 
-      // i = 3 ODD 
-      for (int i = 1; i < 4; i++) { 
-        Group group = new Group(3, i); 
- 
-        ApplicationMessage appMsg = new ApplicationMessage(); 
-        appMsg.setContentObject("Message GroupID: " + i); 
-        groupManager.sendGroupcastMessage(appMsg, group); 
-      } 
-    } catch (IOException e) { 
-      e.printStackTrace(); 
-    } 
-  } 
- 
-  @Override 
-  public void reconnected(NodeConnection remoteCon, SocketAddress endPoint, boolean wasHandover, boolean wasMandatory) {} 
- 
-  @Override 
-  public void disconnected(NodeConnection remoteCon) {} 
- 
-  @Override 
-  public void newMessageReceived(NodeConnection remoteCon, Message message) { 
-    System.out.println(message.getContentObject()); 
-  } 
- 
-  @Override 
-  public void unsentMessages(NodeConnection remoteCon, List<Message> unsentMessages) {} 
- 
-  @Override 
-  public void internalException(NodeConnection remoteCon, Exception e) {} 
- 
-  @Override 
-  public void enteringGroups(List<Group> groups) {} 
- 
-  @Override 
-  public void leavingGroups(List<Group> groups) {} 
-} 
- 
-</file> 
- 
-===== HelloGroupDefinerExecution ===== 
  
  • hellogroup.txt
  • Last modified: 2017/07/21 03:08
  • (external edit)