diff --git a/assignments/src/MV3500Cohort2023MarchJune/homework2/Chojnacki/MulticastUdpReceiver.java b/assignments/src/MV3500Cohort2023MarchJune/homework2/Chojnacki/MulticastUdpReceiver.java new file mode 100644 index 0000000000000000000000000000000000000000..597349a4f8b46c323faed738e2dc9cba4d2c1235 --- /dev/null +++ b/assignments/src/MV3500Cohort2023MarchJune/homework2/Chojnacki/MulticastUdpReceiver.java @@ -0,0 +1,125 @@ +package MV3500Cohort2023MarchJune.homework2.Chojnacki; + +import edu.nps.moves.dis7.utilities.DisThreadedNetworkInterface; +import java.io.*; +import java.net.*; +import java.nio.ByteBuffer; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * Modified the receiver to close after receiving 10 packets. + * + * @author Bruce Chojnacki + */ +public class MulticastUdpReceiver +{ + /** Default constructor */ + public MulticastUdpReceiver() + { + // default constructor + } + // reserved range for all IPv4 multicast: 224.0.0.0 through 239.255.255.255 + // https://en.wikipedia.org/wiki/Multicast_address + // https://www.iana.org/assignments/multicast-addresses/multicast-addresses.xhtml + private static final String MULTICAST_ADDRESS = "239.1.2.15"; + private static final int DESTINATION_PORT = 1718; + + /** + * Time to live: how many router-decrement levels can be crossed + */ + private static final int TTL = 10; + + private static final boolean INFINITE_READ_LOOP = true; + private static NetworkInterface ni; + + /** + * Program invocation, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + MulticastSocket multicastSocket = null; + InetSocketAddress group = null; + ByteBuffer buffer = ByteBuffer.allocate(1500); + DatagramPacket packet = new DatagramPacket(buffer.array(), buffer.capacity()); + + try { + System.out.println("UdpExamples.MulticastUdpReceiver started..."); + + // This is a java/IPv6 problem. You should also add it to the + // arguments used to start the app, eg -Djava.net.preferIPv4Stack=true + // set in the "run" section of preferences. Also, typically + // netbeans must be restarted after these settings. + // https://stackoverflow.com/questions/18747134/getting-cant-assign-requested-address-java-net-socketexception-using-ehcache + System.setProperty("java.net.preferIPv4Stack", "true"); + + multicastSocket = new MulticastSocket(DESTINATION_PORT); + multicastSocket.setTimeToLive(TTL); + InetAddress multicastAddress = InetAddress.getByName(MULTICAST_ADDRESS); + + group = new InetSocketAddress(multicastAddress, DESTINATION_PORT); + + // Join group useful on receiving side + multicastSocket.joinGroup(group, ni = DisThreadedNetworkInterface.findIpv4Interface()); + // You can join multiple groups here + + System.out.println("Multicast address/port: " + multicastAddress.getHostAddress() + "/" + DESTINATION_PORT); + System.out.println("Multicast packets received log:"); + + int index, count = 0; // initialize + float firstFloat, secondFloat; + StringBuilder firstCharacters = new StringBuilder(); + char nextChar; + + while (true) { + multicastSocket.receive(packet); + count++; + + nextChar = ' '; + while (nextChar != ';') // read and build string until terminator ; found + { + nextChar = buffer.getChar(); + firstCharacters.append(nextChar); + } + if (firstCharacters.toString().contains(MulticastUdpSender.QUIT_SENTINEL)) { + System.out.println("Received sentinel \"" + MulticastUdpSender.QUIT_SENTINEL + "\""); + if (!INFINITE_READ_LOOP) { + break; // exit out of reading loop + } + } + index = buffer.getInt(); + firstFloat = buffer.getFloat(); + secondFloat = buffer.getFloat(); + buffer.clear(); + + if (count < 10) { + System.out.print(" "); // prettier output formatting + } + System.out.print(count + ". \"" + firstCharacters + "\" "); // wrap string in quote marks + System.out.println("index=" + index + ", firstFloat=" + firstFloat + " secondFloat=" + secondFloat); + + System.out.println("MulticastReceiver loop complete."); + firstCharacters.setLength(0); + if (count >= 10) { + break; + } + } + } catch (IOException e) { + System.err.println("Problem with MulticastReceiver, see exception trace:"); + System.err.println(e); + } finally // clean up after exit condition + { + if (multicastSocket != null && !multicastSocket.isClosed()) { + try { + multicastSocket.leaveGroup(group, ni); + } catch (IOException ex) { + Logger.getLogger(MulticastUdpReceiver.class.getName()).log(Level.SEVERE, null, ex); + } + multicastSocket.close(); + } + // socket/database/completion cleanup code can go here, if needed. + System.out.println("MulticastReceiver has received all of the packets!"); + } + } +} diff --git a/assignments/src/MV3500Cohort2023MarchJune/homework2/Chojnacki/MulticastUdpSender.java b/assignments/src/MV3500Cohort2023MarchJune/homework2/Chojnacki/MulticastUdpSender.java new file mode 100644 index 0000000000000000000000000000000000000000..a61668e1f6fec5a2a0baa509247096b28a114491 --- /dev/null +++ b/assignments/src/MV3500Cohort2023MarchJune/homework2/Chojnacki/MulticastUdpSender.java @@ -0,0 +1,148 @@ +package MV3500Cohort2023MarchJune.homework2.Chojnacki; + +import edu.nps.moves.dis7.utilities.DisThreadedNetworkInterface; +import java.io.*; +import java.net.*; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * Modified original code. The sender strings have been modified and include + * a time stamp. + * + * @author Bruce CHojnacki + */ +public class MulticastUdpSender { + + /** + * Default constructor + */ + public MulticastUdpSender() { + // default constructor + } + // reserved range for all IPv4 multicast: 224.0.0.0 through 239.255.255.255 + // https://www.iana.org/assignments/multicast-addresses/multicast-addresses.xhtml + + /** + * Default multicast group address for send and receive connections. + * + * @see + * <a href="https://en.wikipedia.org/wiki/Multicast_address">https://en.wikipedia.org/wiki/Multicast_address</a> + */ + public static final String MULTICAST_ADDRESS = "239.1.2.15"; // within reserved multicast address range + /** + * Default socket port used, matches Wireshark DIS capture default + * + * @see + * <a href="https://en.wikipedia.org/wiki/Port_(computer_networking)">https://en.wikipedia.org/wiki/Port_(computer_networking)</a> + */ + public static final int DESTINATION_PORT = 1718; + + /** + * Time to live: how many router-decrement levels can be crossed + */ + public static final int TTL = 10; + + /** + * How many packets to send prior to termination + */ + public static final int LOOPSIZE = 10; // or maybe 20000 + + /** + * Receiving this message causes termination + * + * @see + * <a href="https://en.wikipedia.org/wiki/Sentinel_value">https://en.wikipedia.org/wiki/Sentinel_value</a> + */ + public static final String QUIT_SENTINEL = "I surrender!"; + private static NetworkInterface ni; + + /** + * Program invocation, execution starts here + * + * @param args command-line arguments + * @throws java.io.IOException execution error + */ + @SuppressWarnings("SleepWhileInLoop") + public static void main(String[] args) throws IOException { + MulticastSocket multicastSocket = null; + InetSocketAddress group = null; + + // Put together a message with binary content. "ByteArrayOutputStream" + // is a java.io utility that lets us put together an array of binary + // data, which we put into the UDP packet. + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + DataOutputStream dos = new DataOutputStream(baos); + + try { + System.out.println("I am multicasting 10 packets..."); + // This is a java/IPv6 problem. You should also add it to the + // arguments used to start the app, eg -Djava.net.preferIPv4Stack=true + // set in the "run" section of preferences. Also, typically + // netbeans must be restarted after these settings. + // https://stackoverflow.com/questions/18747134/getting-cant-assign-requested-address-java-net-socketexception-using-ehcache + System.setProperty("java.net.preferIPv4Stack", "true"); + + // multicast group we are sending to--not a single host + multicastSocket = new MulticastSocket(/*DESTINATION_PORT*/); + multicastSocket.setTimeToLive(TTL); // time to live reduces scope of transmission + InetAddress multicastAddress = InetAddress.getByName(MULTICAST_ADDRESS); + System.out.println("Multicast address/port: " + multicastAddress.getHostAddress() + "/" + DESTINATION_PORT); + + group = new InetSocketAddress(multicastAddress, DESTINATION_PORT); + // Join group useful on receiving side + multicastSocket.joinGroup(group, ni = DisThreadedNetworkInterface.findIpv4Interface()); + // You can join multiple groups here + + byte[] buffer = baos.toByteArray(); + DatagramPacket packet = new DatagramPacket(buffer, buffer.length, group/*, DESTINATION_PORT*/); + + for (int index = 0; index < LOOPSIZE; index++) { + // Put together an updated packet to send + if (index < LOOPSIZE - 1) { + // Put together an updated packet to send + + String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(Calendar.getInstance().getTime()); + dos.writeChars("We have found " + System.getProperty("user.name") + " at time: " + timeStamp + "\n"); + dos.writeChars("MulticastSender packet " + Integer.toString(index) + ";"); // string chars for readability + dos.writeInt(index); // arbitrary data, needs Java or byte-alignment to read + dos.writeFloat(17.0f); // arbitrary data, needs Java or byte-alignment to read + dos.writeFloat(23.0f); // arbitrary data, needs Java or byte-alignment to read + } else { + dos.writeChars(QUIT_SENTINEL + ";"); // note string must include ; semicolon as termination sentinel + } + buffer = baos.toByteArray(); + packet.setData(buffer); + multicastSocket.send(packet); + System.out.println("Sent multicast packet " + (index + 1) + " of " + LOOPSIZE); + baos.reset(); + + // How fast does this go? Does UDP try to slow it down, or does + // this cause network problems? (hint: yes for an unlimited send + // rate, unlike TCP). How do you know on the receiving side + // that you haven't received a duplicate UDP packet, out of + // order packet, or dropped packet? Necessary considerations. + Thread.sleep(1000); // Send 100, one per second + } + System.out.println("MulticastSender complete."); + } catch (IOException | InterruptedException e) { + System.err.println("Problem with MulticastSender, see exception trace:"); + System.err.println(e); + } finally { + + if (multicastSocket != null && !multicastSocket.isClosed()) { + try { + multicastSocket.leaveGroup(group, ni); + } catch (IOException ex) { + Logger.getLogger(MulticastUdpSender.class.getName()).log(Level.SEVERE, null, ex); + } + multicastSocket.close(); + } + + dos.close(); + } + } + +}