diff --git a/udp.py b/udp.py
new file mode 100644
index 0000000000000000000000000000000000000000..d54f55f170d490c456e266cb4ac40afeb3e01517
--- /dev/null
+++ b/udp.py
@@ -0,0 +1,104 @@
+import asyncio, websockets, json, base64, time
+from struct import pack
+
+def display_packet(message):
+    #get parts of the header and the payload to display. Convert header parts to int and decode payload from bytes
+    #get source port as int - identifies the sender's port
+    source_port = int.from_bytes(message[0:2], 'little')
+    #get destination port as int - indentifies the server's port
+    dest_port = int.from_bytes(message[2:4], 'little')
+    #get length of UDP message as int - includes header and payload (minimum amount of bytes is 8)
+    length = int.from_bytes(message[4:6], 'little')
+    #get checksum as int - used for error-checking for the header/payload
+    checksum = int.from_bytes(message[6:8], 'little')
+    #get payload from packet - decode it from utf-8
+    payload = message[8:(length+8)].decode("utf-8")
+    #print (decoded) packet details and it's payload 
+    print("Server Sent:", message, "\nDecoded Packet:\nSource Port:", source_port, "\nDest Port:", dest_port, "\nData Length:", length, "\nChecksum:", checksum, "\nPayload:", payload, "\n")
+
+async def udp():
+    #connect to server with specified port
+    uri = "ws://localhost:5612"
+    async with websockets.connect(uri) as websocket:
+        #receive welcome packet from server
+        message = await recv_and_decode_packet(websocket)
+        #display welcome packet
+        display_packet(message)
+        #loop forever
+        while True:
+            #send packet to server with specified parameters
+            await send_packet(websocket, 0, 542, b'1111')
+            #receive the packet the server sent back
+            message = await recv_and_decode_packet(websocket)
+            #delay by one second
+            time.sleep(1)
+            #display the packet the server sent back
+            display_packet(message)
+
+async def send_packet(websocket, dest_port, source_port, message):
+    #calculate checksum of packet/payload
+    checksum_bytes = int(compute_checksum(source_port, dest_port, message)).to_bytes(2, 'little')
+    #convert destination port to bytes
+    dest_bytes = int(dest_port).to_bytes(2, 'little')
+    #convert source port to bytes
+    source_bytes = int(source_port).to_bytes(2, 'little')
+    #convert length of payload to bytes
+    length = int(len(message)).to_bytes(2, 'little')
+    #construct packet with information that is converted into bytes
+    packet = dest_bytes + source_bytes + length + checksum_bytes + message 
+
+    #encode the bytes of packet with base64
+    packet = base64.encodebytes(packet)
+
+    #send packet to server
+    await websocket.send(packet)
+
+async def recv_and_decode_packet(websocket):
+    #receive packer from server
+    packet = await websocket.recv()
+    #display encoded packet
+    print(f"Base64: {packet}")
+    #return decoded packet
+    return base64.b64decode(packet)
+
+def compute_checksum(source, dest, payload):
+    #convert source port to bytes
+    source_bytes = int(source).to_bytes(2, 'little')
+    #convert destination port to bytes
+    dest_bytes = int(dest).to_bytes(2, 'little')
+    #convert length of payload to bytes
+    length_bytes = int(len(payload)).to_bytes(2, 'little')
+    #set bytes as 0
+    size = bytes(2)
+    #construct packet
+    packet = dest_bytes + source_bytes + length_bytes + size + payload
+
+    #initialise checksum as 0
+    checksum = 0
+    #length of the packet
+    length = len(packet)
+    #convert length of packet to bytes
+    size = length.to_bytes(2, 'little')
+
+    #pre-process data for when the size of the packet isn't even.
+    if (length % 2 != 0):
+        #increase the length of the packet by 1
+        length += 1
+        #pad packet with the byte '0' to make it even in length
+        packet += pack('!B', 0)
+
+    #for every two bytes in the packet
+    for i in range(0,len(packet),2):
+        #add the two bytes together - bitshift first byte by 8
+        w = ((packet[i]) << 8) + ((packet[i + 1]))
+        #add onto the total checksum (running sum)
+        checksum += w
+
+    #bitshift checksum to 16 bits
+    checksum = (checksum >> 16) + (checksum & 0xFFFF)
+    #one's compliment of checksum
+    checksum = ~checksum & 0xFFFF
+    #return the checksum
+    return checksum
+
+asyncio.run(udp())