Skip to content

Instantly share code, notes, and snippets.

@lukesteensen
Created April 2, 2012 02:39
Show Gist options
  • Save lukesteensen/2280160 to your computer and use it in GitHub Desktop.
Save lukesteensen/2280160 to your computer and use it in GitHub Desktop.
Reliable UDP
import socket
import struct
import sys
if (len(sys.argv) < 3):
print "arguments needed: <port> <filename>"
exit()
UDP_IP = ''
UDP_PORT = int(sys.argv[1])
FILE = sys.argv[2]
sock = socket.socket( socket.AF_INET, socket.SOCK_DGRAM )
sock.bind( (UDP_IP, UDP_PORT) )
packets = {}
while True:
data, addr = sock.recvfrom( 2048 ) # buffer size is 2048 bytes
syn, total, msg = struct.unpack('!II1400s', data)
sock.sendto( struct.pack('4sI', 'ack:', syn), (addr[0], UDP_PORT + 1) )
print "received packet " + str(syn) + " of " + str(total)
print "sent ack for packet " + str(syn)
packets[syn] = msg
if len(packets) == total:
print "got all packets"
break
print "writing to file"
f = open(FILE, "wb")
try:
for syn, data in sorted(packets.iteritems()):
f.write(data)
except:
print "Error writing file"
finally:
f.close()
print "done."
import threading
import socket
import struct
import sys
from time import sleep, time
if (len(sys.argv) < 4):
print "arguments needed: <hostname> <port> <filename>"
exit()
UDP_IP = socket.gethostbyname(sys.argv[1])
UDP_PORT = int(sys.argv[2])
FILE = sys.argv[3]
print "UDP target IP:", UDP_IP
print "UDP target port:", UDP_PORT
PACKET_SIZE = 1400
packets = {}
f = open(FILE, "rb")
try:
bytes = f.read(PACKET_SIZE)
i = 0
while bytes != "":
packets[i] = bytes
bytes = f.read(PACKET_SIZE)
i = i + 1
except:
print "Error reading file"
finally:
f.close()
print "preparing to send " + str(len(packets)) + " packets..."
sock = socket.socket( socket.AF_INET, # Internet
socket.SOCK_DGRAM ) # UDP
acked_packets = set()
class AckListener(threading.Thread):
def __init__(self, ip, port):
threading.Thread.__init__(self)
self.sock = socket.socket( socket.AF_INET, socket.SOCK_DGRAM )
self.ip = ip
self.port = port
def run(self):
sock.bind( (self.ip, self.port) )
print 'listening for acks...'
while len(acked_packets) < len(packets):
data, addr = sock.recvfrom(1024)
msg, syn = struct.unpack('4sI', data)
if msg == 'ack:':
acked_packets.add(syn)
print "got ack for packet " + str(syn)
listener = AckListener('', UDP_PORT + 1)
listener.start()
start = time()
sent_packets = set()
while len(acked_packets) < len(packets):
# until all the packets have been acked, keep sending all the packets that haven't been acked
for syn, data in packets.iteritems():
if syn not in acked_packets:
packed = struct.pack('!II1400s', syn, len(packets), data)
print "sending packet " + str(syn)
sock.sendto( packed, (UDP_IP, UDP_PORT) )
sent_packets.add(syn)
timeout = 0
while len(sent_packets) - len(acked_packets) > 60:
timeout += 1
sleep(0.001)
if timeout >= 5000:
break
listener.join()
end = time()
elapsed = end - start
print "done in " + str(elapsed) + " seconds"
print "throughput is " + str(10485760 / elapsed) + " bytes / second"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment