Switched to real network communication, not just calling methods on objects

This commit is contained in:
senft-lap 2012-11-15 20:10:38 +01:00
parent a7043d1522
commit 303042078c
23 changed files with 191 additions and 154 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,7 +1,9 @@
package common;
public class MessageType {
public final static byte BOOTSTRAP = 0;
public final static byte INVITE = 7;
public final static byte LEAVE = 1;
public final static byte NEW_NEIGHBOUR = 1;
public final static byte NEW_NEIGHBOR_IPV4 = 4;
public final static byte NEW_NEIGHBOR_IPV6 = 6;
}

View File

@ -1,8 +1,9 @@
package network;
import java.io.IOException;
import java.util.logging.LogManager;
import peer.Peer;
import peer.Node;
public class Network {
@ -23,12 +24,20 @@ public class Network {
e.printStackTrace();
}
Peer a = new Peer("A");
Node a = new Node();
a.spawn("B");
a.spawn("C");
a.spawn("D");
a.leave();
try {
Node b = a.spawn();
Node c = a.spawn();
Node d = a.spawn();
a.leave();
b.leave();
c.leave();
d.leave();
} catch (IOException e) {
e.printStackTrace();
}
}
}

View File

@ -1,125 +1,215 @@
package peer;
import java.io.IOException;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.DatagramChannel;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Logger;
import common.MessageType;
public class Node {
private final static Logger LOGGER = Logger.getLogger(Node.class.getName());
// node id must be unique! id = IP of peer ?!?
// -> Should be unique if we don't consider peers behind a NAT.
private int id;
private static final int BUF_SIZE = 256;
private String name;
private DatagramChannel channel;
private ByteBuffer buf;
private List<Node> neighbours = new ArrayList<Node>();
private String name = "Not initialized";
public Node(int id, String name) {
this.id = id;
this.name = name;
private List<SocketAddress> neighbors = new ArrayList<SocketAddress>();
private Thread thread;
private UDPListen udpListen;
public Node() {
try {
channel = DatagramChannel.open();
channel.socket().bind(null);
buf = ByteBuffer.allocate(BUF_SIZE);
this.name = channel.getLocalAddress().toString();
udpListen = new UDPListen();
thread = new Thread(udpListen);
thread.start();
LOGGER.info("Initialized node " + name);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Add one single neighbour
* Create another peer, mutually link creator and spawn.
*
* @param neighbour
* @return
* @throws IOException
*/
public void addSingleNeighbour(Node neighbour) {
public Node spawn() throws IOException {
LOGGER.info("Name: " + getName() + ", Spawning new node.");
Iterator<Node> it = this.neighbours.iterator();
// create a new node
Node newNode = new Node();
if (!it.hasNext()) { // list of neighbours is empty
this.neighbours.add(neighbour);
} else {
// check if neighbour is already in list
while (it.hasNext()) {
if (it.next().getId() == neighbour.getId()) {
return;
buf.clear();
buf.put(MessageType.INVITE);
buf.flip();
try {
channel.send(buf, newNode.getAddress());
} catch (IOException e) {
e.printStackTrace();
}
neighbors.add(newNode.getAddress());
return newNode;
}
public SocketAddress getAddress() {
try {
return channel.getLocalAddress();
} catch (IOException e) {
LOGGER.severe("Address not set yet.");
}
return null;
}
private byte[] addrToByte(SocketAddress addr) {
// TODO Wäre cool, die IP nicht einfach als String zu schicken.
// Was machen mit IPV4 vs IPV6?
String s = addr.toString();
return s.getBytes();
}
/**
* Circularly link all neighbors, remove itself form all neighbors and exit.
*/
public void leave() {
LOGGER.info("Name: " + getName() + ", Leaving...");
for (int i = 0; i < neighbors.size(); i++) {
if (neighbors.size() > 1) {
buf.clear();
buf.put(MessageType.NEW_NEIGHBOR_IPV6);
if (i == 0) {
buf.put(addrToByte(neighbors.get(1)));
buf.put(addrToByte(neighbors.get(neighbors.size() - 1)));
} else if (i == neighbors.size() - 1) {
buf.put(addrToByte(neighbors.get(0)));
buf.put(addrToByte(neighbors.get(i - 1)));
} else {
buf.put(addrToByte(neighbors.get(i - 1)));
buf.put(addrToByte(neighbors.get(i + 1)));
}
buf.flip();
try {
channel.send(buf, neighbors.get(i));
} catch (IOException e) {
e.printStackTrace();
}
}
this.neighbours.add(neighbour);
}
printInfos();
}
/**
* Add a list of new neighbours
*
* @param neighbours
*/
public void addMultiNeighbours(List<Node> neighbours) {
Iterator<Node> it = neighbours.iterator();
while (it.hasNext()) {
addSingleNeighbour(it.next());
}
}
buf.clear();
buf.put(MessageType.LEAVE);
buf.flip();
/**
* Checks if actual node has neighbour with given id -> remove it
*
* @param node
*/
public void removeNeighbour(Node node) {
for (int i = 0; i < this.neighbours.size(); i++) {
Node tmp = this.neighbours.get(i);
if (tmp.id == node.id) {
this.neighbours.remove(i);
try {
channel.send(buf, neighbors.get(i));
} catch (IOException e) {
e.printStackTrace();
}
}
printInfos();
}
public boolean hasNeighbours() {
return (this.neighbours.size() > 0);
}
/**
* checks if actual node has neighbour with given id
*
* @param id
* @return
*/
public boolean hasNeighbour(int id) {
for (int i = 0; i < neighbours.size(); i++) {
Node tmp = neighbours.get(i);
if (tmp.id == id) {
return true;
try {
if (thread != null) {
udpListen.terminate();
thread.join();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
return false;
}
public int getId() {
return this.id;
}
public List<Node> getNeighbours() {
return this.neighbours;
public boolean hasNeighbors() {
return (this.neighbors.size() > 0);
}
public String getName() {
return this.name;
}
/**
* TODO: Wenn die richtig implementiert ist, ist die
* {@link #removeNeighbour(Node) removeNeighbour} ein Einzeiler.
*/
public boolean equals(Object o) {
return false;
}
public void printInfos() {
StringBuilder result = new StringBuilder(128);
result.append("Name: " + this.name + ", Neighbours: ");
for (int i = 0; i < this.neighbours.size(); i++) {
result.append(this.neighbours.get(i).name + ", ");
for (int i = 0; i < this.neighbors.size(); i++) {
result.append(this.neighbors.get(i).toString() + ", ");
}
LOGGER.info(result.toString());
}
}
public class UDPListen implements Runnable {
private volatile boolean running = true;
public void run() {
while (running) {
SocketAddress receivedFrom = null;
buf.clear();
try {
receivedFrom = channel.receive(buf);
} catch (IOException e) {
e.printStackTrace();
}
buf.flip();
byte messageType = buf.get();
switch (messageType) {
case MessageType.INVITE:
LOGGER.info(name + " received invite from "
+ receivedFrom.toString());
break;
case MessageType.LEAVE:
neighbors.remove(receivedFrom);
break;
case MessageType.NEW_NEIGHBOR_IPV4:
LOGGER.info(name + " received new IPV4 neighbor"
+ receivedFrom.toString() + ": "
+ new String(buf.array()));
break;
case MessageType.NEW_NEIGHBOR_IPV6:
LOGGER.info(name + " received new IPV6 neighbor"
+ receivedFrom.toString() + ": "
+ new String(buf.array()));
break;
default:
LOGGER.info(name + " received unknown command from "
+ receivedFrom.toString() + ": "
+ new String(buf.array()));
}
}
}
public void terminate() {
running = false;
}
}
}

View File

@ -1,52 +0,0 @@
package peer;
import java.util.List;
import java.util.Random;
import java.util.logging.Logger;
public class Peer {
private final static Logger LOGGER = Logger.getLogger(Node.class.getName());
private Node node;
public Peer(String name) {
this.node = new Node(new Random().nextInt(), name);
}
public Node getNode() {
return this.node;
}
/**
* Create another peer, mutually link creator and spawn.
*/
public void spawn(String name) {
LOGGER.info("Name: " + node.getName() + ", Spawning " + name);
// create a new node
Node spawnNode = new Node(new Random().nextInt(), name);
spawnNode.addSingleNeighbour(this.node);
// link new node to actual node
this.node.addSingleNeighbour(spawnNode);
}
/**
* Circularly link all neighbours, remove itself form all neighbours and
* exit.
*/
public void leave() {
LOGGER.info("Name: " + node.getName() + ", Leaving...");
List<Node> neighbours = this.node.getNeighbours();
for (int i = 0; i < neighbours.size(); i++) {
// add all neighbours
neighbours.get(i).addMultiNeighbours(neighbours);
// remove itself
neighbours.get(i).removeNeighbour(this.node);
}
}
}

View File

@ -1,12 +0,0 @@
package peer;
public class UDPListen extends Thread {
public UDPListen(int port) {
}
public void run() {
}
}