Sunteți pe pagina 1din 16

CSE1004

Assessment 07
Stop & Wait and GoBack N ARQ
17BCE0309
LAKHAN SOLANKI

Flow control Mechanisms


Flow control is the process of managing the rate of data transmission between two nodes to
prevent a fast sender from overwhelming a slow receiver. It provides a mechanism for the
receiver to control the transmission speed, so that the receiving node is not overwhelmed with
data from transmitting node. Flow control mechanisms can be classified by whether or not
the receiving node sends feedback to the sending node. Flow control is important because it
is possible for a sending computer to transmit information at a faster rate than the destination
computer can receive and process it. This can happen if the receiving computers have a heavy
traffic load in comparison to the sending computer, or if the receiving computer has less
processing power than the sending computer.

Stop and Wait ARQ


Stop-and-wait flow control is the simplest form of flow control. In this method, the receiver
indicates its readiness to receive data for each frame, the message is broken into multiple
frames. The sender waits for an ACK (acknowledgement) after every frame for specified
time (called time out). It is sent to ensure that the receiver has received the frame correctly.
It will then send the next frame only after the ACK has been received.
The problem with Stop-and wait is that only one frame can be transmitted at a time, and that
often leads to inefficient transmission, because until the sender receives the ACK it cannot
transmit any new packet. During this time both the sender and the channel are unutilised.

Advantages
The only advantage of this method of flow control is its simplicity.

DIsadvantages

Network and
Communication
CSE1004

The sender needs to wait for the ACK after every frame it transmits. This is a source of
inefficiency, and is particularly bad when the propagation delay is much longer than the
transmission delay.
Stop and wait can also create inefficiencies when sending longer transmissions. When longer
transmissions are sent there is more likely chance for error in this protocol. If the messages
are short the errors are more likely to be detected early. More inefficiency is created when
single messages are broken into separate frames because it makes the transmission longer.

Algorithm
Sender: Transmits a single frame at a time.
Receiver: Transmits acknowledgement (ACK) as it receives a frame.
Sender receive ACK within time out.
Go to step 1.
If a frame or ACK is lost during transmission then it has to be transmitted again by sender.
This re-transmission process is known as ARQ (automatic repeat request)

Implementation Source Code:

Server:
import socket s = socket.socket()
print( "Socket successfully created" ) port = 12345
s.bind(('', port))
print ("socket binded to %s" %(port))
s.listen(1)
print ( "socket is listening" ) c,
addr = s.accept() ackReq = 1 while True:
data = str ( input ( 'Enter data to send: ' )) if(data == 'Exit' ):
c.send(data.encode('ascii'))
break else:
ack = (ackReq+1)%2 while(ack != ackReq):
c.send(data.encode ( 'ascii')) ack = int((c.recv(1024)).decode( 'ascii'))
if(ack == ackReq):
ackReq = (ackReq+1)%2 print('Successful Acknowledgement Received' )
break
c.close()

Client:
import socket
import random
s = socket.socket() port = 12345 ack = int(random()*2)
s.connect(('127.0.0.1', port)) while True:
data = (s.recv(1024)).decode('ascii') if data:
Network and
Communication
CSE1004

print(data)
s.send(str( ack).encode ('ascii' )) ack = int(random()*2) if(data=='Exit'):
break
else:
s.send ( str (( ack+1 ) %2 ). encode ( 'ascii'))
s.close()
Output:

Server

Client

Network and
Communication
CSE1004

Sliding Window
A method of flow control in which a receiver gives a transmitter permission to transmit data
until a window is full. When the window is full, the transmitter must stop transmitting until
the receiver advertises a larger window.

Sliding-window flow control is best utilized when the buffer size is limited and pre-
established. During a typical communication between a sender and a receiver the receiver
allocates buffer space for n frames (n is the buffer size in frames). The sender can send and
the receiver can accept n frames without having to wait for an acknowledgement. A
sequence number is assigned to frames in order to help keep track of those frames which did
receive an acknowledgement. The receiver acknowledges a frame by sending an
acknowledgement that includes the sequence number of the next frame expected. This
acknowledgement announces that the receiver is ready to receive n frames, beginning with the
number specified. Both the sender and receiver maintain what is called a window. The size
of the window is less than or equal to the buffer size.

Network and
Communication
CSE1004

Sliding window flow control has a far better performance than stop-and-wait flow control.
For example, in a wireless environment if data rates are low and noise level is very high, waiting
for an acknowledgement for every packet that is transferred is not very feasible. Therefore,
transferring data as a bulk would yield a better performance in terms of higher throughput.

Sliding window flow control is a point to point protocol assuming that no other entity tries to
communicate until the current data transfer is complete. The window maintained by the
sender indicates which frames he can send. The sender sends all the frames in the window
and waits for an acknowledgement (as opposed to acknowledging after every frame). The
sender then shifts the window to the corresponding sequence number, thus indicating that
frames within the window starting from the current sequence number can be sent.

GoBack N ARQ
Go-Back-N ARQ is a specific instance of the automatic repeat request (ARQ) protocol, in
which the sending process continues to send a number of frames specified by a window size
even without receiving an acknowledgement (ACK) packet from the receiver. It is a special
case of the general sliding window protocol with the transmit window size of N and receive
window size of 1. It can transmit N frames to the peer before requiring an ACK.

The receiver process keeps track of the sequence number of the next frame it expects to
receive, and sends that number with every ACK it sends. The receiver will discard any frame
that does not have the exact sequence number it expects (either a duplicate frame it already
acknowledged, or an out-of-order frame it expects to receive later) and will resend an ACK
for the last correct in-order frame. Once the sender has sent all of the frames in its window, it
will detect that all of the frames since the first lost frame are outstanding, and will go back to the
sequence number of the last ACK it received from the receiver process and fill its window
starting with that frame and continue the process over again.

Go-Back-N ARQ is a more efficient use of a connection than Stop-and-wait ARQ, since unlike
waiting for an acknowledgement for each packet, the connection is still being utilized as packets
are being sent. In other words, during the time that would otherwise be spent waiting, more
packets are being sent. However, this method also results in sending frames multiple times –
if any frame was lost or damaged, or the ACK acknowledging them was lost or damaged, then
that frame and all following frames in the window (even if they were received without error)
will be re-sent. An automatic repeat request (ARQ) algorithm, used for error correction, in
which a negative acknowledgement (NAK) causes retransmission of the word in error as well
as the previous N–1 words. The value of N is usually chosen such that the time taken to
Network and
Communication
CSE1004

transmit the N words is less than the round trip delay from transmitter to receiver and back
again. Therefore, a buffer is not needed at the receiver.

Algorithm
N = window size
Rn = request number
Sn = sequence number
Sb = sequence base Sm = sequence max Receiver:
○ Rn = 0
○ Do the following forever:
If the packet received = Rn and the packet is error free Accept the packet and send it to a
higher layer
Rn = Rn + 1
Else
Refuse packet ,Send a Request for Rn
Sender:
Sb = 0
Sm = N + 1
Repeat the following steps forever:
If you receive a request number where Rn > Sb
Sm = (Sm - Sb) + Rn
Sb = Rn
If no packet is in transmission,
Transmit a packet where Sb <= Sn <= Sm. Packets are transmitted in order.

Implementation
Source Code:
Server: import
socket import
time import
os import hashlib
import random

host = ""
port = 60000

def check_sum(data):
hash_md5 = hashlib.md5() hash_md5.update(data)
return hash_md5. hexdigest ()

class Sender:

Network and
Communication
CSE1004

def __init__(self, win_size, timeout, num_packets):


self.w = win_size self.t = timeout self.n = num_packets self.filename =
"sample.txt" self.cur_seq = 0 self.active_spaces = self.w
self.window = win_size * [ None ] self.soc = socket.socket()
self.last_sent_seqnum = -1
self.last_ack_seqnum = - 1
self.logfile = ''

def canAdd(self): # check if a packet can be added to the send window


if self.active_spaces == 0:
return False else :
return True

def sendPack(self, pack): # function to send the packet through the socket
time.sleep(1.5 ) conn.send ( pack)
print "Sending packet No.", int(pack.split('/////')[1])
self.logfile.write(time.ctime(time.time()) + "\t" +
str ( pack.split ( '/////' )[ 1 ]) + "Sending\n" )

def add(self, pack): # add a packet to the send window self.last_sent_seqnum =


self. cur_seq
self.cur_seq += 1
self.window[self.w - self.active_spaces] = pack
self.active_spaces -= 1
self.sendPack(pack)

def resend(self): # function to resend packet if lost cur_num = 0


while cur_num < self.w - self.active_spaces :
print "Resending: ", str( self.window [ cur_num].split('/////')[1])
self.logfile.write(time.ctime (
time.time()) + "\t" + str( self.window [cur_num].split
( '/////' )[ 1 ]) + "Re-sending\n")
time.sleep(1.4)
temp = self.window [ cur_num].split ( '/////' )
self.window[cur_num] = temp[0 ] + '/////' + temp[1 ] + '/////' + temp[2 ]
+ '/////' + temp[3] + '/////' + str(random.randint(70 , 100 ))
print self.window[cur_num].split('/////' )

conn.send(self.window[cur_num]) cur_num += 1

def makePack(self, num, pac): # Create a packet


sequence_number = num file_check_sum = check_sum(pac) pack_size
= len(pac) prob = random.randint(0, 100) packet =
str(file_check_sum) + '/////' + str ( sequence_number) + \
'/////' + str(pack_size) + '/////' + \

Network and
Communication
CSE1004

str(pac) + '/////' + str(prob)


return packet

def divide(self, data, num): # create packets from datas lis = [] while
data:
lis.append(data[:num])
data = data[num:]
return lis

def acc_Acks(self): # check if all the sent packets have been ACKed
try:
packet = conn.recv(1024) print packet.split('/////')
except :
print 'Connection lost due to timeout!' self.logfile.write(time.ctime (time.time())
+ "\t" + str(self.last_ack_seqnum + 1) + "Lost TImeout")
return 0
if packet.split('/////')[ 2 ] == "NAK" :
return 0
print "Recieved Ack number: ", packet.split( '/////')[1] print "\n"
if int(packet.split ( '/////' )[ 1 ]) == self.last_ack_seqnum + 1:
self.last_ack_seqnum = int( packet.split ( '/////' )[ 1 ])
self.window.pop(0)
self.window.append(None)
self.active_spaces += 1
return 1

elif int(packet.split('/////')[1]) > self.last_ack_seqnum + 1:


k = self.last_ack_seqnum
while(k < int(packet.split('/////')[1])):
self.window.pop(0) self.window. append ( None)
self.active_spaces += 1
k= k+ 1
self.last_ack_seqnum = int(packet.split('/////')[1]) return 1

else:
return 0

def sendmess(self, pack_list, length): # send the messages till all packets are sent
cur_pack = 0
while (cur_pack < length or self.last_ack_seqnum != length - 1):
#print "hjff"
while self.canAdd() and cur_pack != length:
pack = self.makePack(cur_pack, pack_list[cur_pack])
cur_pack = cur_pack + 1
print pack.split('/////' ) self.add ( pack)
print "\n"
Network and
Communication
CSE1004

#print "wwaaaaattt"
if self.acc_Acks() == 0:
time.sleep(1) self.resend() print
"END"
time.sleep ( 1 ) conn.send("$$$$$$$")

def run ( self): # run this to send packets from the file
try:
fil = open(self.filename , 'rb' ) data = fil.read()
pack_list = self.divide ( data, 7 )
fil.close()
except IOError:
print "No such file exists" fname="servlog.txt"
self.logfile = open ( os.curdir + "/" + fname, "w+" )
l=len(pack_list)
self.sendmess(pack_list, l)

win = raw_input("Enter window size: ")


numpac = raw_input("Enter the number of packets: ") tim = raw_input("Enter the
timeout: ") server=Sender(int ( win), float (tim), int ( numpac))
server.soc.bind(( host, port))
server.soc . listen ( 5 ) conn, addr=server.soc . accept () data =
conn.recv(1024) print "recieved connection" conn.send(str(win) + "/////" +
str ( tim) + "/////" + "sample.txt" ) conn.close()
server.soc.settimeout(5) conn, addr = server.soc.accept() data = conn.recv(1024)
server.run()
conn.close()

Client:
import socket import time import os import hashlib
import random

host = "" port = 60000

def check_sum(data): hash_md5 = hashlib.md5()


hash_md5.update(data) return hash_md5.hexdigest()

class Reciever:

def __init__(self,win_size, timeout, filename):


self.w = win_size self.completeData = '' self.t = timeout self.rec_file = ''

Network and
Communication
CSE1004

self.base = 0 self.expec_seqnum = 0 self.last_ack_sent = - 1 self.soc


= socket.socket() self.window = [None] * self.w
self.active_win_packets = self.w
self.fileclone = filename self.logfile = '' self.filepointer = 0

def canAdd ( self): # check if a packet can be added to the send window
if self.active_win_packets == 0:
return False else:
return True

def createResponse ( self, seq_num, typ):


mess_check_sum = check_sum(str ( seq_num))
return str(mess_check_sum) + "/////" + str(seq_num) + "/////" + typ

def sendAcks ( self, packet, counter): if counter == -1:


self.logfile.write(time.ctime (time.time()) + "\t" +
str(packet.split('/////')[ 1]) +
"Recieving\n")
time.sleep(1.7) self.soc.send(packet)
print "Sending ack: ", str(packet.split('/////')[1]) + "NAK\n"
return self.last_ack_sent = int(packet.split("/////")[1]) + counter
time.sleep(1.7) self.soc.send(packet) self.logfile.write(time.ctime
(time.time()) + "\t" + str(packet.split('/////')[ 1]) + "Recieving\n")
print "Sending ack: " , str(packet.split('/////')[1]) + "ACK\n"

def remove(self, poin):


#print self.window[0], self.window.index(str(poin))
self.window[self.window. index ( poin)] = None
self.active_win_packets += 1

def add ( self, packet):


pack = packet.split('/////')[ 3 ] seqnum =
int(packet.split('/////')[1])
#print packet#, self.window[seqnum % self.w] if self.window [
seqnum % self.w ] == None : if seqnum ==
self.expec_seqnum : self.logfile.write(time.ctime (
time.time()) + "\t" + str( packet.split( '/////' )[ 1 ]) + "Recieve\n"
) self.active_win_packets -= 1
self.window[seqnum % self.w] = packet elif seqnum >
self.expec_seqnum: self.logfile .write(time.ctime (
time.time()) + "\t" + str( packet.split( '/////' )[1]) + "Recieving
buffer\n") self.active_win_packets -= 1
self.window[seqnum % self.w] = packet

else:

Network and
Communication
CSE1004

print "In buffer!", packet.split('/////' )[1]

def appData(self):
self.completeData += self. window[ self.filepointer ]. split (
'/////' )[ 3 ] self.filepointer += 1 self.remove( self.window
[ self.filepointer - 1 ]) if self.filepointer >= self.w:
self.filepointer = 0

def rMessage(self):
while True: pack = self.soc.recv(1024)
#print pack coun = 0
#print pack.split('\t')
print (pack.split('/////'))
if pack == '$$$$$$$': #print "ya"
f = open(self.fileclone, 'wb') f.write( self.completeData
)
f.close()
break
elif int(pack.split('/////' )[1]) == self.expec_seqnum:
nex = 0
if self.canAdd(): try:
k = int(pack.split( "/////")[4]) except:
nex = 1
if not nex:
if int(pack.split("/////")[4 ]) > 70:
self.add( pack) packet = self.createResponse(self.expec_seqnum + coun,
"ACK" ) while self.window[(
int(pack.split('/////')[1]) + coun) % self.w ] != None :
self.appData() coun = coun + 1
else:
packet = self.createResponse(self.expec_seqnum + coun, "NAK")
else:
packet = self.createResponse(self.expec_seqnum + coun, "NAK")
#print "ggg"
self.sendAcks( packet, coun - 1 )
self.expec_seqnum = self.expec_seqnum + coun
else:
# print int(pack.split('/////')[1]) if self.canAdd():
self.add(pack)

def recieve(self): self.logfile = open(os.curdir + '/' + "clientlog.txt",


'wb') self.rMessage ()
self.logfile.close()

Network and
Communication
CSE1004

s = socket.socket()
s.connect((host, port))
s.send("Hello Server") mess = s.recv(1024) args = mess.split("/////")
s.close() client = Reciever(int ( args[0 ]) , float (args[1]) , args[2])
print "recieved arguments" client.soc.connect(( host, port)) client.soc.send("Hello
server" ) client.recieve()
client.soc.close()
Output:

Server

Client

Network and
Communication
CSE1004

ASSIGNMENT 08

Floting window: Selective Repeat ARQ

1.Aim
Selective Repeat is part of the automatic repeat-request (ARQ). With selective repeat, the
sender sends a number of frames specified by a window size even without the need to
wait for individual ACK from the receiver as in Go-Back-N ARQ. The receiver may
selectively reject a single frame, which may be retransmitted alone; this contrasts with
other forms of ARQ, which must send every frame from that point again. The receiver
accepts out-of-order frames and buffers them. The sender individually retransmits frames
that have timed out.

2.Concept Explanation
It may be used as a protocol for the delivery and acknowledgement of message units, or it
may be used as a protocol for the delivery of subdivided message sub-units.
When used as the protocol for the delivery of messages, the sending process continues to
send a number of frames specified by a window size even after a frame loss. Unlike Go-
Back-N ARQ, the receiving process will continue to accept and acknowledge frames sent
after an initial error; this is the general case of the sliding window protocol with both
transmit and receive window sizes greater than 1.The receiver process keeps track of the
sequence number of the earliest frame it has not received, and sends that number with
every acknowledgement (ACK) it sends.

3.Algorithm/Pseudocode
1. Start.
2. Establish connection (recommended UDP)
3. Accept the window size from the client(should be <=40)

Network and
Communication
CSE1004

4. Accept the packets from the network layer.


5. Calculate the total frames/windows required.
6. Send the details to the client(totalpackets,totalframes.)
7. Initialise the transmit buffer.
8. Built the frame/window depending on the windowsize.
9. Transmit the frame.
10. Wait for the acknowledgement frame.
11. Check for the acknowledgement of each packet and repeat the
process for the packet for which the negative acknowledgement isreceived.
Else continue as usual.
12. Increment the frame count and repeat steps 7 to 12 until all packets
are
transmitted.
13. Close the connection.
14.Stop.

4.Program code
Server:

from socket import *


import socket
s = socket.socket(AF_INET, SOCK_DGRAM)
s.bind(('127.0.0.1', 3999))
winSize, client = s.recvfrom(1024)
winSize = int(winSize.decode('ascii'))
data = input('Enter data to send: ')
frame_Size = int(input('Enter size of frame: '))
framesReq = int(len(data)/frame_Size)
s.sendto(str(1).encode('ascii'),client)
s.sendto(str(framesReq).encode('ascii'),client)
done = []
for i in range(framesReq):
s.sendto((data[(i)*frame_Size:(i+1)*frame_Size]).encode('ascii'),client)
while True:
ack,addr = s.recvfrom(1024)
ack = ack.decode('ascii')
print(ack)
while (ack[0:2] == 'NAK'):

Network and
Communication
CSE1004

s.sendto((data[(int(ack[3]))*frame_Size:(int(ack[3])+1)*frame_Size]).enco
de('ascii'),client)
ack = s.recvfrom(1024).decode('ascii')
if(ack[0:2] == 'ACK'):
done += [int(ack[3])-1]
if(len(done) == framesReq):
break
s.close()

Client:

from socket import *


import socket
s = socket.socket(AF_INET, SOCK_DGRAM)
server= ('127.0.0.1', 3999)
winSize = input('Enter window size: ')
s.sendto(winSize.encode('ascii'), server)
totalPackets, address = s.recvfrom(1024)
totalPackets = int(totalPackets.decode('ascii'))
totalFrames, address = s.recvfrom(1024)
totalFrames = int(totalFrames.decode('ascii'))
recv = 0
fData = [None]*totalFrames
for recv in range(totalFrames):
data, address = s.recvfrom(1024)
fData[recv] = data.decode('ascii')
print(fData[recv], data.decode('ascii'))
ack = 0
i=0
while i < totalFrames:
if fData[i]:
s.sendto(("ACK" + str(i+1)).encode('ascii'), server)
i += 1
else:
while fData[i] == None:

Network and
Communication
CSE1004

s.sendto(("NAK" + str(i)).encode('ascii'),server)
datai, address = s.recvfrom(1024)
fData[i] = datai.decode('ascii')

s.sendto(("ACK" + str(i+1)).encode('ascii'), server)


i += 1
s.close()
for i in range(totalFrames):
print(fData[i])

5.Output
server

Client

Network and
Communication

S-ar putea să vă placă și