I'd like to implement a sliding window mechanism into the following code, looking for any advice on where to start.
Currently the sender keeps sending and collecting its own packets, and I'm not really sure why that is, could someone help me fix that and guide me in the right direction for implementing the protocol?
Thanks
sender.py
import sys
from Queue import Queue
from state import StateMachine
import rdtlib
from rdtlib import rdt_send, udt_send, isACK, iscorrupt, rdt_rcv
# Globals
lastsndpkt = None # Holds last sent packet in case it needs to be retransmitted
nextseqnum = 0
base = 0
sent = 0
retrans = 0
# Set up a queue of packets to send
sendbuf = Queue()
for i in 'ABCDEFGHIJ':
sendbuf.put(i)
# Handle the sender's 'Wait for call from above' state
def sender_wait_above():
global lastsndpkt, nextseqnum, sent
print 'Sender in state WAIT_ABOVE'
# If we have some data to send, send it using nextseqnum
if not sendbuf.empty():
lastsndpkt = rdt_send(sendbuf.get(), nextseqnum)
sent += 1
# Advance nextseqnum for next packet that will be sent
nextseqnum += 1
return 'WAIT_ACK' # Wait for the ACK
else:
return 'S_END' # Terminate state machine
# Handle the sender's 'Wait for ACK' state
def sender_wait_ack():
global lastsndpkt, retrans, base
print 'Sender in state WAIT_ACK'
# Wait to receive an ACK packet
packet = rdt_rcv(timeout=None)
# TODO: These three error condtions could be collapsed into a single case
if packet == None: # Timeout!
print 'Sender: Timeout, retransmitting', lastsndpkt
udt_send(lastsndpkt)
retrans += 1
return 'WAIT_ACK'
if iscorrupt(packet):
print 'Sender: Corrupt ACK, retransmitting', lastsndpkt
udt_send(lastsndpkt)
retrans += 1
return 'WAIT_ACK'
if not isACK(packet, base):
print 'Sender: Duplicate ACK, retransmitting', lastsndpkt
udt_send(lastsndpkt)
retrans += 1
return 'WAIT_ACK'
# Expected ACK is received, advance base of sender window by 1
if isACK(packet, base):
base += 1
return 'WAIT_ABOVE'
# Default case, keep waiting for an ACK
return 'WAIT_ACK'
def SenderDone():
print 'Send buffer empty, exiting'
print 'Sent: ', sent
print 'Retransmitted: ', retrans
#
# Set up the state machine
#
def start_sender():
sender = StateMachine('sender')
sender.add_state('WAIT_ABOVE', sender_wait_above)
sender.add_state('WAIT_ACK', sender_wait_ack)
sender.add_state('S_END', SenderDone, end_state=1)
sender.set_initial_state('WAIT_ABOVE')
sender.run()
rdtlib.peer = ('10.0.0.2', 12002)
start_sender()
receiver.py
import sys
from state import StateMachine
import rdtlib
from rdtlib import udt_send, rdt_send, rdt_rcv, deliver_data, make_pkt, extract, iscorrupt, hasSeq, ACK
# Globals
expectedseqnum = 0
sndpkt = make_pkt(type=ACK, seq=expectedseqnum)
# Handle the receiver's 'Wait for call from below' states
#
# There are three cases to handle for each of these:
# 1. Packet is corrupt
# 2. Packet is out-of-sequence
# 3. Packet is OK
def receiver_wait_below():
global expectedseqnum, sndpkt
print 'Receiver in state WAIT_BELOW, expecting seqnum', expectedseqnum
packet = rdt_rcv()
# We have a good packet with the expected seqnum, so deliver data
# to app layer and send an acknowledgement
if (not iscorrupt(packet)) and hasSeq(packet, expectedseqnum):
# Extract data and pass to application layer
data = extract(packet)
deliver_data(data)
# Prepare an ACK pack for this seqnum
print 'Receiver: packet OK, sending ACK for', expectedseqnum
sndpkt = make_pkt(type=ACK, seq=expectedseqnum)
# Increment seqnum
expectedseqnum += 1
else:
# The packet received is either corrupt or out-of-sequence,
# send the last ACK packet
# TODO: print error message that indicates what is wrong
print 'Receiver: bad packet, sending last ACK'
# Send the ACK packet to the sender
udt_send(sndpkt)
return 'WAIT_BELOW'
def ReceiverDone():
pass
#
# Set up the state machine
#
def start_receiver():
receiver = StateMachine('receiver')
receiver.add_state('WAIT_BELOW', receiver_wait_below)
receiver.add_state('R_END', ReceiverDone, end_state=1)
receiver.set_initial_state('WAIT_BELOW')
receiver.run()
rdtlib.peer = ('10.0.0.1', 12002)
start_receiver()