Created
January 31, 2014 16:32
-
-
Save akkaash/8735655 to your computer and use it in GitHub Desktop.
FTP: Selective Repeat using UDP
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
__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() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
__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