forked from KrunalPatel27/ReliableCommunication
-
Notifications
You must be signed in to change notification settings - Fork 0
/
hw5.py
108 lines (95 loc) · 3.4 KB
/
hw5.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
"""
Where solution code to HW5 should be written. No other files should
be modified.
"""
import socket
import io
import time
import typing
import struct
import homework5
import homework5.logging
def send(sock: socket.socket, data: bytes):
"""
Implementation of the sending logic for sending data over a slow,
lossy, constrained network.
Args:
sock -- A socket object, constructed and initialized to communicate
over a simulated lossy network.
data -- A bytes object, containing the data to send over the network.
"""
# Naive implementation where we chunk the data to be sent into
# packets as large as the network will allow, and then send them
# over the network, pausing half a second between sends to let the
# network "rest" :)
timeoutInterval = 1.0
headerSize = 4
logger = homework5.logging.get_logger("hw5-sender")
chunk_size = homework5.MAX_PACKET - headerSize
packetCount= 1
pause = 2.0
avgRTT = 0
lastRTT = 0
tripCount = 1
sequenceNumber = 0
offsets = range(0, len(data), chunk_size)
for chunk in [data[i:i + chunk_size] for i in offsets]:
sequenceNumber = packetCount * chunk_size
packetCount = packetCount + 1
chunk = struct.pack("i", sequenceNumber) + chunk
sock.send(chunk)
start = time.time()
logger.info("Pausing for %f seconds", round(pause, 2))
if packetCount != 2:
pause = computeTimeout(avgRTT, lastRTT)
sock.settimeout(pause)
while True:
try:
data = sock.recv(headerSize)
tempSequenceNumber = struct.unpack("i", data[:4])[0]
if tempSequenceNumber == sequenceNumber:
lastRTT = time.time() - start
avgRTT = (( (tripCount -1) * avgRTT) + lastRTT)/(tripCount)
tripCount = tripCount + 1
break
except:
pause = computeTimeout((avgRTT+1.0), pause)
sock.send(chunk)
start = time.time()
if packetCount == 2:
pause = 2.0
sock.settimeout(pause)
def computeTimeout(avgRTT, lastRTT):
return (0.8* avgRTT) + (.2*lastRTT)
def recv(sock: socket.socket, dest: io.BufferedIOBase) -> int:
"""
Implementation of the receiving logic for receiving data over a slow,
lossy, constrained network.
Args:
sock -- A socket object, constructed and initialized to communicate
over a simulated lossy network.
Return:
The number of bytes written to the destination.
"""
logger = homework5.logging.get_logger("hw5-receiver")
# Naive solution, where we continually read data off the socket
# until we don't receive any more data, and then return.
num_bytes = 0
sequenceNumber = 0
while True:
data = sock.recv(homework5.MAX_PACKET)
if not data:
break
header = data[:4]
data = data[4:]
tempNumber = struct.unpack("i", header)[0]
if data[4:] is b'':
break
logger.info("Received %d bytes", len(data))
if tempNumber > sequenceNumber:
sequenceNumber = tempNumber
dest.write(data)
num_bytes += len(data)
dest.flush()
sock.send(struct.pack("i", sequenceNumber))
return num_bytes