Skip to content

Instantly share code, notes, and snippets.

@akkaash
Created January 31, 2014 16:32
Show Gist options
  • Save akkaash/8735655 to your computer and use it in GitHub Desktop.
Save akkaash/8735655 to your computer and use it in GitHub Desktop.
FTP: Selective Repeat using UDP
__author__ = 'akkaash'
import sys
import socket
import threading
import signal
SERVER_HOSTNAME = sys.argv[1] # server on this ip
SERVER_SENDING_PORT = int(sys.argv[2]) # server on this port
FILE_NAME = sys.argv[3] # send this file
N = int(sys.argv[4]) # window size
MSS = int(sys.argv[5]) # maximum segment size of the data
SERVER_ACK_PORT = SERVER_SENDING_PORT + 1
CLIENT_SENDING_PORT = int(sys.argv[6])
CLIENT_ACK_PORT = CLIENT_SENDING_PORT + 1
timeout = False
mLock = threading.Lock()
clientSendingSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
clientSendingSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
clientSendingSocket.bind(('', CLIENT_SENDING_PORT))
clientAckSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
clientAckSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
clientAckSocket.bind(('', CLIENT_ACK_PORT))
packetList = []
nPackets = 0
sequenceNo = 0
oddFlag = 0
dataPacket = int('0101010101010101', 2)
bufferAck = []
def get_sequence_no(packet):
return str(packet).split(':', 1)[0]
def chunks(message, n):
for i in xrange(0, len(message), n):
yield message[i:i+n]
def end_around_carry(a, b):
c = a + b
return (c & 0xffff) + (c >> 16)
def checksum(msg, flag):
s = 0
for i in range(0, len(msg), 2):
if flag == 0:
w = ord(msg[i]) + (ord(msg[i+1]) << 8)
elif flag == 1:
w = ord('0') + (ord(msg[i]) << 8)
s = end_around_carry(s, w)
ret = ~s & 0xffff
return ret
expectedAckNo = 0
receivedAckNo = -1
sentSeqNo = -1
# ------------------------------
#reading the entire file
fd = open(FILE_NAME, 'rb')
completeFile = fd.read()
fd.close()
# creating the packets..
for chunk in chunks(completeFile, MSS):
if len(chunk) % 2 != 0:
oddFlag = 1
chunkChecksum = checksum(chunk, oddFlag)
packet = str(sequenceNo) + ":" + str(chunkChecksum) + ":" + str(dataPacket) + ":" + chunk
packetList.append(packet)
sequenceNo += 1
maxSequenceNo = sequenceNo - 1
print 'max sequence no:', maxSequenceNo
# ------------------------------
def timeout_handler(signum, frame):
print '---------timeout----------'
global timeout, expectedAckNo, receivedAckNo, sentSeqNo
timeout = True
if receivedAckNo < maxSequenceNo:
sentSeqNo = receivedAckNo
signal.setitimer(signal.ITIMER_REAL, 0.9)
#signal.alarm(2)
signal.signal(signal.SIGALRM, timeout_handler)
blip = 'blip1'
print blip
clientSendingSocket.sendto(blip, (SERVER_HOSTNAME, SERVER_SENDING_PORT))
print 'sent1'
blip = 'blip2'
print blip
clientAckSocket.sendto(blip, (SERVER_HOSTNAME, SERVER_ACK_PORT))
print 'sent2'
class AckThread(threading.Thread):
def __init__(self, sock):
threading.Thread.__init__(self)
self.ack_listener_socket = sock
print 'thread init'
def run(self):
print 'thread started'
global expectedAckNo, receivedAckNo, sentSeqNo
while True:
data, address = self.ack_listener_socket.recvfrom(20)
l = str(data).split(':')
with mLock:
if l[1] == 'ack':
if l[0] == 'bye':
print data
return
print '-> ', data
if int(l[0]) > expectedAckNo:
print 'received ack for greater sequence no.'
bufferAck.append(int(l[0]))
bufferAck.sort()
elif int(l[0]) == expectedAckNo:
print 'expectedAckNo ', int(l[0])
receivedAckNo += 1
expectedAckNo += 1
print 'regular update ->', receivedAckNo
signal.setitimer(signal.ITIMER_REAL, 0.9)
while bufferAck and bufferAck[0] == receivedAckNo + 1:
print 'getting ack from buffer->', bufferAck[0]
del bufferAck[0]
receivedAckNo += 1
expectedAckNo += 1
print 'update through buffer->', receivedAckNo
signal.setitimer(signal.ITIMER_REAL, 0.9)
bufferAck.sort()
mssPacket = 'mss:' + str(MSS)
clientSendingSocket.sendto(mssPacket, (SERVER_HOSTNAME, SERVER_SENDING_PORT))
mssAck = clientSendingSocket.recv(10)
if mssAck == 'mss:ack':
print 'mssAck: ', mssAck
t = AckThread(clientAckSocket)
t.start()
signal.setitimer(signal.ITIMER_REAL, 0.9)
while int(receivedAckNo) < int(maxSequenceNo):
#print 'receivedAckNo', receivedAckNo, ' maxSequence ', maxSequenceNo
with mLock:
while sentSeqNo - receivedAckNo < N:
sentSeqNo += 1
if sentSeqNo > maxSequenceNo:
break
print 'sending:', sentSeqNo
d = packetList[sentSeqNo]
clientSendingSocket.sendto(d, (SERVER_HOSTNAME, SERVER_SENDING_PORT))
print 'sent:', sentSeqNo
continue
endPacket = 'bye'
clientSendingSocket.sendto(endPacket, (SERVER_HOSTNAME, SERVER_SENDING_PORT))
print 'reached end'
t.join()
__author__ = 'akkaash'
import sys
import socket
import random
import shutil
globalCount = 0
M_HOSTNAME = ''
M_RECEIVING_PORT = int(sys.argv[1])
FNAME = sys.argv[2]
P = float(sys.argv[3])
M_ACK_PORT = M_RECEIVING_PORT + 1
serverReceivingSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
serverReceivingSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
serverReceivingSocket.bind(('', M_RECEIVING_PORT))
serverAckSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
serverAckSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
serverAckSocket.bind(('', M_ACK_PORT))
#print serverAckSocket
print M_RECEIVING_PORT, M_ACK_PORT
print 'in here'
d, a = serverReceivingSocket.recvfrom(20)
print 'done here'
CLIENT_HOSTNAME = a[0]
CLIENT_SENDING_PORT = a[1]
print str(d)
blipAck = str(d) + ':' + 'ack'
#serverReceivingSocket.sendto(blipAck, (CLIENT_HOSTNAME, CLIENT_SENDING_PORT))
d, a = serverAckSocket.recvfrom(20)
CLIENT_HOSTNAME = a[0]
CLIENT_ACK_PORT = a[1]
print str(d)
blipAck = str(d) + ':' + 'ack'
#serverAckSocket.sendto(blipAck, (CLIENT_HOSTNAME, CLIENT_ACK_PORT))
nextAckSeqNo = 0
fileDes = open(FNAME, 'wb')
d, a = serverReceivingSocket.recvfrom(20)
MSS = str(d).split(':')[1]
print 'mss = ', int(MSS)
mssAck = 'mss:ack'
serverReceivingSocket.sendto(mssAck, a)
packetList = {}
while True:
print 'nextAckSeqNo -> ', nextAckSeqNo
data, address = serverReceivingSocket.recvfrom(int(MSS)+3+20)
if str(data) == 'bye':
byePacket = 'bye:ack'
serverAckSocket.sendto(byePacket, (CLIENT_HOSTNAME, CLIENT_ACK_PORT))
break
r = random.random()
l = str(data).split(':', 3)
ackPacket = str(l[0]) + ':' + 'ack'
if r <= P:
print 'Packet loss, sequence number = ', l[0]
continue
else:
#print 'accepted part:', l[0]
if int(l[0]) < nextAckSeqNo:
print 'ack gapchi maara'
serverAckSocket.sendto(ackPacket, (CLIENT_HOSTNAME, CLIENT_ACK_PORT))
elif int(l[0]) == nextAckSeqNo:
packetList[int(l[0])] = str(l[3])
print 'ackPacket:', ackPacket
serverAckSocket.sendto(ackPacket, (CLIENT_HOSTNAME, CLIENT_ACK_PORT))
nextAckSeqNo += 1
continue
else:
print 'out of sequence packet sending ack'
print 'adding to dict'
packetList[int(l[0])] = str(l[3])
print 'added'
print '->out of seq ack ', ackPacket
serverAckSocket.sendto(ackPacket, (CLIENT_HOSTNAME, CLIENT_ACK_PORT))
for i in range(0, len(packetList)):
if not packetList.has_key(i):
print i, ' = False'
print 'unexpected exception!'
break
else:
fileDes.write(packetList[i])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment