3 * Time-stamp: "2007-11-06 18:12:55 anton"
6 import java
.io
.FileWriter
;
7 import java
.io
.BufferedWriter
;
8 import java
.io
.IOException
;
10 import java
.net
.InetAddress
;
11 import java
.net
.DatagramSocket
;
12 import java
.net
.DatagramPacket
;
13 import java
.net
.SocketException
;
16 * UDPNode – a node in a UDP packet ring.
18 * @author "Anton Johansson" <anton.johansson@gmail.com>
19 * @author "Victor Zamanian" <victor.zamanian@gmail.com>
21 public class UDPNode
extends Node
{
24 private DatagramSocket mySocket
= null;
27 * Creates a new UDPNode instance with all necessary information.
29 * @param localPort the local port to listen to
30 * @param nextHost the host to connect to
31 * @param nextPort the port that <code>nextHost</code> listens to
32 * @param logger determines if this node should log lap-times
34 public UDPNode(int localPort
,
40 super(localPort
, nextHost
, nextPort
, logger
);
41 // open a DatagramSocket
43 this.mySocket
= new DatagramSocket(localPort
);
45 catch (SocketException e
) {
46 System
.out
.println(e
);
50 // if this node is a logging node
52 logFileName
= "lap-times-udp.log";
54 file
= new FileWriter(logFileName
);
55 out
= new BufferedWriter(file
);
57 catch (IOException e
) {
58 System
.out
.println(e
);
64 * Runs the main logic of the UDPNode
66 public void runUDPNode() {
68 // keeps track of whether or not the
69 // main while-loop should be running
70 boolean runMainWhileLoop
= true;
72 // start phase 1 by sending out a find-master query
73 sendPacket(constructPacket(FINDMASTER
, new Integer(ID
).toString()));
75 // initate fields used to store information from arrived packets
76 byte[] receivedData
= new byte[DATAGRAMSIZE
];
77 DatagramPacket receivePacket
=
78 new DatagramPacket(receivedData
, DATAGRAMSIZE
);
80 // start receiving packets ('main while-loop')
81 while (runMainWhileLoop
) {
82 // Waiting for data to arrive
83 receivePacket(receivePacket
);
85 // acquire the message's message type
86 int messageType
= receivedData
[0];
88 // keeping track of which phase we're in
89 int phase
= FINDMASTER
;
90 switch (messageType
) {
91 // if messageType == 1
94 // acquire the message's length
95 int messageLength
= receivedData
[1];
97 // acquire the message...
99 new String(receivedData
).substring(2, messageLength
+ 2);
101 // the largest ID that this packet has seen so far, i.e. the
102 // ID of the node with the largest ID so far in the ring.
103 int receivedID
= Integer
.parseInt(message
);
105 // if we left phase 1 but messages
106 // are still circling the ring:
107 if (phase
!= FINDMASTER
) {
108 // don't do anything.
111 // if this node will surely not be the master node
112 if (receivedID
> ID
) {
113 // set a new receiver for the received packet
114 receivePacket
.setPort(nextPort
);
115 receivePacket
.setAddress(nextHost
);
116 sendPacket(receivePacket
);
118 // if this node has a larger ID than the one of the sending node
119 else if (receivedID
< ID
) {
120 // Send own ID again since it could have been lost
121 sendPacket(constructPacket(FINDMASTER
, new Integer(ID
).toString()));
123 // if this node should be the master node
124 else if (receivedID
== ID
) {
128 // if this node is a logging node,
130 // set the starting time -- the time
131 // when phase two was initiated
132 startTime
= System
.nanoTime();
134 // increase the number of sent packets.
137 // send first packet in phase two
138 sendPacket(constructPacket(RUNMODE
, new Integer(ID
).toString()));
141 // if messageType == 2
143 // make sure everybody knows we're in the second phase
146 // if this node is a logger and the start time hasn't been set
147 if (isLogger
&& startTime
== 0) {
148 // set the start time
149 startTime
= System
.nanoTime();
151 // if this node is a logger:
154 writeToLog(new String(receivedData
).substring(2, receivedData
[1] + 2));
156 // if this is the master node and
157 // we've sent as many packets as we were to (and the
158 // number of packets to send is not zero (infinitely many)):
159 if (isMasterNode
&& sentPackets
== PACKETSTOSEND
) {
160 // send the terminating packet to the next node
161 // (and, indirectly so, to all other nodes)
162 sendPacket(constructPacket(TERMINATE
, "3"));
166 // if we've not send as many packets as we are to:
167 // re-route packet (set its port and address) and send it
168 receivePacket
.setPort(nextPort
);
169 receivePacket
.setAddress(nextHost
);
170 sendPacket(receivePacket
);
173 // if messageType == 3 (stop sending packets and ultimately quit
175 runMainWhileLoop
= false;
176 // if this node is a logger, log one final time before
177 // stopping the whole shebang and close the file
179 writeToLog(new String(receivedData
).substring(2, receivedData
[1] + 2));
180 System
.out
.println("Closing file...");
182 System
.out
.println("Finished.");
184 // send terminating packet (end the whole shebang)
185 sendPacket(constructPacket(TERMINATE
, "3"));
189 } // end main while-loop
193 * Sends a DatagramPacket through this UDPNode's DatagramSocket.
195 * @return boolean <code>true</code> if sending was successful,
196 * else <code>false</code>.
198 public boolean sendPacket(DatagramPacket sendPacket
) {
200 mySocket
.send(sendPacket
);
202 catch (IOException e
) {
203 System
.out
.println(e
);
210 * Receives a DatagramPacket from this UDPNode's DatagramSocket.
212 * @return boolean <code>true</code> if receiving was successful,
213 * else <code>false</code>.
215 public boolean receivePacket(DatagramPacket receivePacket
) {
217 mySocket
.receive(receivePacket
);
219 catch (IOException e
) {
220 System
.out
.println(e
);
227 * For starting the UDPNode from a commandline
229 * @param args should contain local-port next-host next-port [L]
230 * where the L is optional and specifies if the node
231 * should log lap-times
232 * @exception IOException if an error occurs
234 public static void main(String
[] args
) throws IOException
{
235 // args should contain local-port next-host next-port
237 boolean logger
= false;
238 if (args
.length
== 4 && args
[3].charAt(0) == 'L') {
242 node
= new UDPNode(Integer
.parseInt(args
[0]),
243 InetAddress
.getByName(args
[1]),
244 Integer
.parseInt(args
[2]),
247 catch (Exception e
) {
248 System
.out
.println("You most likely provided parameters " +
249 "incorrectly to the program." + '\n' +
250 "Usage: java UDPNode local-port " +
251 "next-host next-port [L]");
257 catch (Exception e
) {
258 System
.out
.println("Something went wrong... Try making sure " +
259 "that the ports you are trying to use " +
260 "are not occupied by any other program.");