From d2ac0bc43718328bd3f228cde7bb87d3d2c4731b Mon Sep 17 00:00:00 2001
From: johns <johns@192.168.2.9>
Date: Mon, 1 May 2023 11:41:27 -0700
Subject: [PATCH] Initial Commit

---
 .../Fredrickson/UnicastUdpReceiver.java       | 114 ++++++++++++++
 .../Fredrickson/UnicastUdpSender.java         | 143 ++++++++++++++++++
 2 files changed, 257 insertions(+)
 create mode 100644 assignments/src/MV3500Cohort2023MarchJune/homework2/Fredrickson/UnicastUdpReceiver.java
 create mode 100644 assignments/src/MV3500Cohort2023MarchJune/homework2/Fredrickson/UnicastUdpSender.java

diff --git a/assignments/src/MV3500Cohort2023MarchJune/homework2/Fredrickson/UnicastUdpReceiver.java b/assignments/src/MV3500Cohort2023MarchJune/homework2/Fredrickson/UnicastUdpReceiver.java
new file mode 100644
index 0000000000..991ef8cf06
--- /dev/null
+++ b/assignments/src/MV3500Cohort2023MarchJune/homework2/Fredrickson/UnicastUdpReceiver.java
@@ -0,0 +1,114 @@
+package MV3500Cohort2023MarchJune.homework2.Fredrickson;
+
+import java.io.*;
+import java.net.*;
+
+/**
+ * An example of receiving UDP packets. Since very often both the
+ * sender and receiver are on the same host we use different ports
+ * for each. This prevents collision complaints from the localhost.
+ * 
+ * Start this before launching UdpSender.
+ *
+ * @see <a href="https://docs.oracle.com/javase/tutorial/networking/datagrams/index.html">https://docs.oracle.com/javase/tutorial/networking/datagrams/index.html</a>
+ * @see <a href="https://docs.oracle.com/javase/tutorial/essential/io/datastreams.html">https://docs.oracle.com/javase/tutorial/essential/io/datastreams.html</a>
+ * @see <a href="https://en.wikipedia.org/wiki/User_Datagram_Protocol">https://en.wikipedia.org/wiki/User_Datagram_Protocol</a>
+ * @author mcgredo
+ * @author brutzman@nps.edu
+ * 
+ * (JOHN FREDRICKSON) I have made the following changes to this code:
+ * -changed output formatting
+ * 
+ */
+public class UnicastUdpReceiver
+{
+    /** Default constructor */
+    public UnicastUdpReceiver()
+    {
+        // default constructor
+    }
+//  public static final int        SENDING_PORT = 1414;        // port used by UdpSender, unneeded here
+    /** socket value of shared interest */
+    public static final int      UDP_PORT = 1415;        // sharable
+    /** socket value of shared interest */
+    public static final String DESTINATION_HOST = "localhost";
+
+    /**
+     * Program invocation, execution starts here
+     * @param args command-line arguments
+     */
+    public static void main(String[] args)
+    {
+        DatagramSocket udpSocket = null;
+        
+        try
+        {
+            System.out.println(UnicastUdpReceiver.class.getName() + " started...");
+            
+            // Create a UDP socket
+            udpSocket = new DatagramSocket(UDP_PORT);
+            udpSocket.setReceiveBufferSize(1500); // how many bytes are in buffer?  MTU=1500 is good
+            udpSocket.setBroadcast(false);        // we're just receiving here
+//            udpSocket.setReuseAddress(true);
+            
+            byte[] byteArray = new byte[1500];
+            DatagramPacket receivePacket = new DatagramPacket(byteArray, byteArray.length);
+            
+            ByteArrayInputStream bais = new ByteArrayInputStream(byteArray);
+            DataInputStream dis = new DataInputStream(bais);
+            
+            boolean       isEvenParity;
+            int           packetCount = 0;
+            int           firstInt;   
+            float         secondFloat;
+            String        thirdString;
+            String        padding;
+            
+            // You need a new receiving packet to read from every packet received
+            while (true)
+            {
+                packetCount++; // good practice to increment counter at start of loop, when possible
+                udpSocket.receive(receivePacket); // blocks until packet is received
+                
+                if (packetCount == 1)
+                {                
+                    if  (udpSocket.getInetAddress() == null)
+                         System.out.println("UdpReceiver address/port: UDP socket address null (loopback)" + "/" + UDP_PORT);
+                    else System.out.println("UdpReceiver address/port: " + udpSocket.getInetAddress().getHostAddress() + "/" + UDP_PORT);
+                }
+
+                // values of interest follow. order and types of what was sent must match what you are reading!
+                firstInt     = dis.readInt();     // packetID
+                secondFloat  = dis.readFloat();
+                thirdString  = dis.readUTF();     // string value with guaranteed encoding, matches UTF-8 is 8 bit
+                isEvenParity = dis.readBoolean(); // ok, we've gotten everything we're looking for.  
+                
+                dis.reset(); // now clear the input stream after reading, in preparation for next loop
+                
+                if  (isEvenParity) 
+                     padding = " ";
+                else padding = "";
+                
+                System.out.println("[" + UnicastUdpReceiver.class.getName() + "]" + 
+                                                    " port="   + UDP_PORT +
+                                                " packetID="   + firstInt +            // have output message use same name as sender
+                                     ", second float value="   + secondFloat  + 
+                                     ", third String value=\"" + thirdString  + "\"" + // note that /" is literal quote character
+                                    " isPacketIdEvenParity="   + isEvenParity + ","  + padding +
+                                     " packet counter="        + packetCount);
+                System.out.println();
+            }
+        }
+        catch(IOException e)
+        {
+            System.err.println("Problem with UdpReceiver, see exception trace:");
+            System.err.println(e);
+        } 
+        finally // clean up prior to exit, don't want to leave behind zombie socket
+        {
+            if (udpSocket != null)
+                udpSocket.close();
+            System.out.println(UnicastUdpReceiver.class.getName() + " complete."); // all done
+        }
+    }
+}
diff --git a/assignments/src/MV3500Cohort2023MarchJune/homework2/Fredrickson/UnicastUdpSender.java b/assignments/src/MV3500Cohort2023MarchJune/homework2/Fredrickson/UnicastUdpSender.java
new file mode 100644
index 0000000000..7863285a7a
--- /dev/null
+++ b/assignments/src/MV3500Cohort2023MarchJune/homework2/Fredrickson/UnicastUdpSender.java
@@ -0,0 +1,143 @@
+package MV3500Cohort2023MarchJune.homework2.Fredrickson;
+
+import java.io.*;
+import java.net.*;
+
+/**
+ * An example of sending UDP packets. The sending and receiving programs
+ * use different UDP ports; there can be problems getting this to work
+ * if both the sending and receiving sockets try to use the same port
+ * on the same host.
+ * 
+ * Start this before launching UdpReceiver.
+ * 
+ * @see <a href="https://docs.oracle.com/javase/tutorial/essential/io/datastreams.html">https://docs.oracle.com/javase/tutorial/essential/io/datastreams.html</a>
+ * @see <a href="https://en.wikipedia.org/wiki/User_Datagram_Protocol">https://en.wikipedia.org/wiki/User_Datagram_Protocol</a>
+ * @see <a href="https://docs.oracle.com/javase/tutorial/essential/environment/sysprop.html">System properties</a>
+ * @author mcgredo
+ * @author brutzman@nps.edu
+ * 
+ *   
+ * (JOHN FREDRICKSON) I have made the following changes to this code:
+ * -changed output formatting
+ * 
+ */
+public class UnicastUdpSender 
+{
+    /** Default constructor */
+    public UnicastUdpSender()
+    {
+        // default constructor
+    }
+    private static final String            MY_NAME = System.getProperty("user.name"); // guru incantation   8)
+//  public  static final int          SENDING_PORT = 1414; // not needed, can let system choose an open local port
+    /** socket value of shared interest */
+    public  static final int              UDP_PORT = UnicastUdpReceiver.UDP_PORT; // 1415; ensure consistent
+    private static final int TOTAL_PACKETS_TO_SEND = 100;
+    
+    /** socket value of shared interest */
+    public static  final String   DESTINATION_HOST = "localhost"; 
+    // here is what we need for lab comms
+//  public static final String   DESTINATION_HOST = "10.1.105.16"; // localhost 127.0.0.1 or argon 10.1.105.1 or 10.1.105.1 or whatever
+    
+    /**
+     * Program invocation, execution starts here
+     * @param args command-line arguments
+     */
+    @SuppressWarnings("SleepWhileInLoop")
+    public static void main(String[] args)
+    {
+        DatagramSocket udpSocket = null;
+        DataOutputStream  dos = null;
+        int   packetID = 0;     // counter variable to send in packet
+        float    countdown = -1.0f; // unreachable value is good sentinel to ensure expected changes occur
+        String message = MY_NAME + " says Hello MV3500"; // no really
+        String padding = new String();
+        
+        try
+        {
+            System.out.println(UnicastUdpSender.class.getName() + " shows how to send simple-type values via DataOutputStream");
+            System.out.println(UnicastUdpSender.class.getName() + " started...");
+            
+            // Create a UDP socket
+            udpSocket = new DatagramSocket(); // let system assign output port, then SENDING_PORT not needed
+            
+            // 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(1500); // how many bytes are in buffer?  MTU=1500 is good
+            dos = new DataOutputStream(baos); // wrapper for writing values, connects both streams
+			
+            // Put together a packet to send
+            // these types and order of variables must match on sender and receiver
+            byte[] byteArray = baos.toByteArray();
+            
+            // ID of the host we are sending to
+            InetAddress destinationAddress = InetAddress.getByName(DESTINATION_HOST);
+            // ID of the host we are sending from
+            InetAddress      sourceAddress = InetAddress.getByName("localhost"); // possibly identical if source not modified
+            
+            DatagramPacket datagramPacket = new DatagramPacket(byteArray, byteArray.length, destinationAddress, UDP_PORT);
+            
+            System.out.println("UdpSender address/port: " + destinationAddress.getHostAddress() + "/" + UDP_PORT);
+       
+            // Hmmm, how fast does UDP stream go? Does UDP effectively slow packets 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? your responsibility.
+            
+            for (int index = 1; index <= TOTAL_PACKETS_TO_SEND; index++) // avoid infinite send loops in code, they can be hard to kill!
+            {
+                packetID++;                               // increment counter, prefer using explicit value to index
+                countdown = TOTAL_PACKETS_TO_SEND - packetID; // countdown from goal total
+                boolean isPacketIdEvenParity = ((packetID % 2) == 0); // % is modulo operator; result 0 is even parity, 1 is odd parity
+                
+                // values of interest follow. order and types of what was sent must match what you are reading!
+                dos.writeInt    (packetID);
+                dos.writeFloat  (countdown);
+                dos.writeUTF    (message); // string value with guaranteed encoding, matches UTF-8 is 8 bit
+                dos.writeBoolean(isPacketIdEvenParity);
+                
+                dos.flush(); // sends DataOutputStream to ByteArrayOutputStream, clearing the buffer
+                byteArray = baos.toByteArray();    // OK so go get the flushed result...
+                datagramPacket.setData(byteArray); // and put it in the packet...
+                udpSocket.send(datagramPacket);    // and send it away. boom gone, nonblocking.
+//              System.out.println("udpSocket output port=" + udpSocket.getLocalPort()); // diagnostic tells what port was chosen by system
+                
+                if  (isPacketIdEvenParity)
+                     padding = " "; // single blank character as a string of length 1
+                else padding = "";  // empty string
+            
+                Thread.sleep(100); // Send packets at rate of one per second
+                System.out.println("[" + UnicastUdpSender.class.getName() + "] " + MY_NAME + " " + sourceAddress +
+                                   " port=" + UDP_PORT +
+                                   " has sent values (" + packetID + "," + countdown + ",\"" + message + "\"," + isPacketIdEvenParity +
+                                   ")" + padding + " as packet #" + index + " of " + TOTAL_PACKETS_TO_SEND);
+                System.out.println();
+                baos.reset(); // clear the output stream after sending
+            }   // end for loop
+        }
+        catch (IOException | InterruptedException e)
+        {
+            System.err.println("Problem with UdpSender, see exception trace:");
+            System.err.println(e);
+        } 
+        finally // clean up prior to exit, don't want to leave behind zombies
+        {
+            if (udpSocket != null)
+                udpSocket.close();
+            try
+            {
+                if (dos != null)
+                    dos.close();
+            }
+            catch (IOException e)
+            {
+                System.err.println("Problem with UdpSender, see exception trace:");
+                System.err.println(e);
+            } 
+            System.out.println(UnicastUdpSender.class.getName() + " complete."); // all done
+        }
+    }
+}
-- 
GitLab