Differences
This shows you the differences between two versions of the page.
hellogroup [2013/09/25 13:58] mroriz [HelloGroupDefinerClient] |
hellogroup [2017/07/21 03:08] |
||
---|---|---|---|
Line 1: | Line 1: | ||
- | ====== HelloGroup ====== | ||
- | {{ : | ||
- | 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]]), | ||
- | |||
- | 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 '' | ||
- | |||
- | 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 '' | ||
- | |||
- | <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. | ||
- | </ | ||
- | |||
- | ===== Group Concept ===== | ||
- | In SDDL, groups are created/ | ||
- | - Implicit: Some of its application message attribute satisfies the membership condition in the group selection logic. For example, its '' | ||
- | - Explicit: The mobile client explicitly joins an existing group through the '' | ||
- | |||
- | 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 '' | ||
- | |||
- | 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 '' | ||
- | |||
- | ===== HelloGroupClient ===== | ||
- | The '' | ||
- | |||
- | To communicate with groups using the '' | ||
- | |||
- | <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, | ||
- | |||
- | private static String | ||
- | private static int gatewayPort | ||
- | private GroupCommunicationManager | ||
- | private Group | ||
- | |||
- | public HelloGroupClient() { | ||
- | InetSocketAddress address = new InetSocketAddress(gatewayIP, | ||
- | 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("" | ||
- | |||
- | 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(" | ||
- | |||
- | groupManager.sendGroupcastMessage(appMsg, | ||
- | } catch (IOException e) { | ||
- | e.printStackTrace(); | ||
- | } | ||
- | } | ||
- | |||
- | @Override | ||
- | public void reconnected(NodeConnection remoteCon, SocketAddress endPoint, boolean wasHandover, | ||
- | |||
- | @Override | ||
- | public void disconnected(NodeConnection remoteCon) {} | ||
- | |||
- | @Override | ||
- | public void newMessageReceived(NodeConnection remoteCon, Message message) { | ||
- | System.out.println(" | ||
- | } | ||
- | |||
- | @Override | ||
- | public void unsentMessages(NodeConnection remoteCon, List< | ||
- | |||
- | @Override | ||
- | public void internalException(NodeConnection remoteCon, Exception e) {} | ||
- | |||
- | @Override | ||
- | public void enteringGroups(List< | ||
- | System.out.println(" | ||
- | } | ||
- | |||
- | @Override | ||
- | public void leavingGroups(List< | ||
- | } | ||
- | </ | ||
- | |||
- | ===== HelloGroupPeer ===== | ||
- | Since group clients and peers are identical, the '' | ||
- | |||
- | <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, | ||
- | |||
- | private static String | ||
- | private static int | ||
- | private GroupCommunicationManager | ||
- | private Group aGroup; | ||
- | |||
- | public HelloGroupPeer() { | ||
- | InetSocketAddress address = new InetSocketAddress(gatewayIP, | ||
- | 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("" | ||
- | |||
- | 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, | ||
- | |||
- | @Override | ||
- | public void disconnected(NodeConnection remoteCon) {} | ||
- | |||
- | @Override | ||
- | public void newMessageReceived(NodeConnection remoteCon, Message message) { | ||
- | System.out.println(" | ||
- | } | ||
- | |||
- | @Override | ||
- | public void unsentMessages(NodeConnection remoteCon, List< | ||
- | |||
- | @Override | ||
- | public void internalException(NodeConnection remoteCon, Exception e) {} | ||
- | |||
- | @Override | ||
- | public void enteringGroups(List< | ||
- | System.out.println(" | ||
- | } | ||
- | |||
- | @Override | ||
- | public void leavingGroups(List< | ||
- | } | ||
- | </ | ||
- | |||
- | ===== 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 '' | ||
- | |||
- | ===== 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, | ||
- | * '' | ||
- | * '' | ||
- | |||
- | 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< | ||
- | System.out.println(" | ||
- | |||
- | // Add the node to two groups | ||
- | HashSet< | ||
- | |||
- | // 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(" | ||
- | return groupCollection; | ||
- | } | ||
- | } | ||
- | </ | ||
- | |||
- | <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(); | ||
- | } | ||
- | } | ||
- | |||
- | } | ||
- | </ | ||
- | ===== HelloGroupReceiver ===== | ||
- | To test our GroupDefiner, | ||
- | |||
- | <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, | ||
- | private final static String | ||
- | private final static int | ||
- | private GroupCommunicationManager | ||
- | |||
- | public HelloGroupDefinerEvenReceiver() { | ||
- | UUID uuid = UUID.randomUUID(); | ||
- | |||
- | while (uuid.getLeastSignificantBits() % 2 != 0) { | ||
- | uuid = UUID.randomUUID(); | ||
- | } | ||
- | InetSocketAddress address = new InetSocketAddress(gatewayIP, | ||
- | 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("" | ||
- | 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, | ||
- | |||
- | @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< | ||
- | |||
- | @Override | ||
- | public void internalException(NodeConnection remoteCon, Exception e) {} | ||
- | |||
- | @Override | ||
- | public void enteringGroups(List< | ||
- | |||
- | @Override | ||
- | public void leavingGroups(List< | ||
- | } | ||
- | </ | ||
- | |||
- | <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, | ||
- | private final static String | ||
- | private final static int | ||
- | private GroupCommunicationManager | ||
- | |||
- | public HelloGroupDefinerOddReceiver() { | ||
- | UUID uuid = UUID.randomUUID(); | ||
- | |||
- | while (uuid.getLeastSignificantBits() % 2 == 0) { | ||
- | uuid = UUID.randomUUID(); | ||
- | } | ||
- | InetSocketAddress address = new InetSocketAddress(gatewayIP, | ||
- | 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("" | ||
- | 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, | ||
- | |||
- | @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< | ||
- | |||
- | @Override | ||
- | public void internalException(NodeConnection remoteCon, Exception e) {} | ||
- | |||
- | @Override | ||
- | public void enteringGroups(List< | ||
- | |||
- | @Override | ||
- | public void leavingGroups(List< | ||
- | } | ||
- | </ | ||
- | |||
- | ===== HelloGroupDefinerClient ===== | ||
- | |||
- | Our client will act slightly the same as the '' | ||
- | |||
- | <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, | ||
- | |||
- | private final static String | ||
- | private final static int | ||
- | private GroupCommunicationManager | ||
- | |||
- | public HelloGroupClient() { | ||
- | InetSocketAddress address = new InetSocketAddress(gatewayIP, | ||
- | 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("" | ||
- | |||
- | 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(" | ||
- | groupManager.sendGroupcastMessage(appMsg, | ||
- | } | ||
- | } catch (IOException e) { | ||
- | e.printStackTrace(); | ||
- | } | ||
- | } | ||
- | |||
- | @Override | ||
- | public void reconnected(NodeConnection remoteCon, SocketAddress endPoint, boolean wasHandover, | ||
- | |||
- | @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< | ||
- | |||
- | @Override | ||
- | public void internalException(NodeConnection remoteCon, Exception e) {} | ||
- | |||
- | @Override | ||
- | public void enteringGroups(List< | ||
- | |||
- | @Override | ||
- | public void leavingGroups(List< | ||
- | } | ||
- | |||
- | </ | ||
- | |||
- | ===== HelloGroupDefinerExecution ===== | ||