diff --git a/assignments/src/MV3500Cohort2020JulySeptember/homework3/Cannon/CannonReceivingSendingScreenshots.pdf b/assignments/src/MV3500Cohort2020JulySeptember/homework3/Cannon/CannonReceivingSendingScreenshots.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..f8999ad7cd6af4f5270ed9c4c22962ae4057b5ea
Binary files /dev/null and b/assignments/src/MV3500Cohort2020JulySeptember/homework3/Cannon/CannonReceivingSendingScreenshots.pdf differ
diff --git a/assignments/src/MV3500Cohort2020JulySeptember/homework3/Cannon/CannonUdpReceiver.java b/assignments/src/MV3500Cohort2020JulySeptember/homework3/Cannon/CannonUdpReceiver.java
new file mode 100644
index 0000000000000000000000000000000000000000..dfbb3430f83c30674323d55bd78a063562248eb2
--- /dev/null
+++ b/assignments/src/MV3500Cohort2020JulySeptember/homework3/Cannon/CannonUdpReceiver.java
@@ -0,0 +1,92 @@
+package MV3500Cohort2020JulySeptember.homework3.Cannon;
+
+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 https://docs.oracle.com/javase/tutorial/essential/io/datastreams.html
+ * @see https://en.wikipedia.org/wiki/User_Datagram_Protocol
+ * @author mcgredo
+ * @author brutzman
+ */
+public class CannonUdpReceiver 
+{
+//  public static final int       SENDING_PORT = 1414; // port used by UdpSender, unneeded here
+    public static final int     RECEIVING_PORT = 1415;
+    public static final String DESINATION_HOST = "localhost";
+
+    /**
+     * @param args the command line arguments
+     * @throws java.io.IOException
+     */
+    public static void main(String[] args) throws IOException 
+    {
+        DatagramSocket udpSocket = null;
+        
+        try
+        {
+            System.out.println(CannonUdpReceiver.class.getName() + " started...");
+            
+            // Create a UDP socket
+            udpSocket = new DatagramSocket(RECEIVING_PORT);
+            udpSocket.setReceiveBufferSize(1500); // how many bytes are in buffer?  MTU=1500 is good
+            udpSocket.setBroadcast(false);        // we're just receiving here
+            
+            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
+                
+                // 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("[" + CannonUdpReceiver.class.getName() + "]" + 
+                                               " 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);
+            }
+        }
+        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(CannonUdpReceiver.class.getName() + " complete."); // all done
+        }
+    }
+}
diff --git a/assignments/src/MV3500Cohort2020JulySeptember/homework3/Cannon/CannonUdpSender.java b/assignments/src/MV3500Cohort2020JulySeptember/homework3/Cannon/CannonUdpSender.java
new file mode 100644
index 0000000000000000000000000000000000000000..471f5e0c49b35e0b6ca23906e218d26faf2b6ce9
--- /dev/null
+++ b/assignments/src/MV3500Cohort2020JulySeptember/homework3/Cannon/CannonUdpSender.java
@@ -0,0 +1,115 @@
+package MV3500Cohort2020JulySeptember.homework3.Cannon;
+
+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 https://docs.oracle.com/javase/tutorial/essential/io/datastreams.html
+ * @see https://en.wikipedia.org/wiki/User_Datagram_Protocol
+ * @author mcgredo
+ * @author brutzman
+ */
+public class CannonUdpSender 
+{
+    // System properties: https://docs.oracle.com/javase/tutorial/essential/environment/sysprop.html
+    public 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
+    public static final int        RECEIVING_PORT = 1415;
+    public static final int TOTAL_PACKETS_TO_SEND = 100;
+    
+    // here is what we need for lab comms
+    public static final String   DESTINATION_HOST = "10.1.105.7"; // localhost 127.0.0.1 or argon 10.1.105.1 or 10.1.105.1 or whatever
+    
+    @SuppressWarnings("SleepWhileInLoop")
+    public static void main(String[] args) throws IOException 
+    {
+        DatagramSocket udpSocket = null;
+        DataOutputStream  dos = null;
+        int   packetID = 0;     // counter variable to send in packet
+        float    value = -1.0f; // unreachable value is good sentinel to ensure expected changes occur
+        String message = MY_NAME + " says we need to understand llamas in order to code"; // no really
+        String padding = new String();
+        
+        try
+        {
+            System.out.println(CannonUdpSender.class.getName() + " shows how to send simple-type values via DataOutputStream");
+            System.out.println(CannonUdpSender.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, RECEIVING_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
+                value = TOTAL_PACKETS_TO_SEND - packetID; // countdown
+                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  (value);
+                dos.writeUTF    (message); // string value with guaranteed encoding, matches UTF-8 is 8 bit
+                dos.writeBoolean(isPacketIdEvenParity);
+                
+                dos.flush(); // sends DataOutputStream to ByteArrayOutputStream
+                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 = " ";
+                else padding = "";
+            
+                Thread.sleep(1000); // Send packets at rate of one per second
+                System.out.println("[" + CannonUdpSender.class.getName() + "] " + MY_NAME + " " + sourceAddress + 
+                                   " sent values(" + packetID + "," + value + ",\"" + message + "\"," + isPacketIdEvenParity +
+                                   ")" + padding + " as packet #" + index + " of " + TOTAL_PACKETS_TO_SEND);
+                baos.reset(); // clear the output stream after sending
+            }
+        }
+        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();
+            
+            if (dos != null)
+                dos.close();
+            System.out.println(CannonUdpSender.class.getName() + " complete."); // all done
+        }
+    }
+}