generated from kevinawalsh/csci356-p4-template
-
Notifications
You must be signed in to change notification settings - Fork 0
/
better.py
151 lines (123 loc) · 5.16 KB
/
better.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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#!/usr/bin/env python3
#
# Author: K. Walsh <[email protected]>
# Modified by: Apurva, Margaret, Michael :)
# Date: 4 April 2017
# Modified: 4 Dec 2020
#
# Our updated version of the Stop-and-wait client.
#
# What we've added: timeouts and retransmissions, reordering, sliding window
#
# Run the program like this:
# python3 client_saw.py 1.2.3.4 6000
# This will send data to a UDP server at IP address 1.2.3.4 port 6000.
import socket
import sys
import time
import struct
import datasource
import trace
# setting verbose = 0 turns off most printing
# setting verbose = 1 turns on a little bit of printing
# setting verbose = 2 turns on a lot of printing
# setting verbose = 3 turns on all printing
verbose = 2
# setting tracefile = None disables writing a trace file for the client
# tracefile = None
tracefile = "client_saw_packets.csv"
magic = 0xBAADCAFE
def main(host, port):
print("Sending UDP packets to %s:%d" % (host, port))
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # Makes a UDP socket!
trace.init(tracefile,
"Log of all packets sent and ACKs received by client",
"SeqNo", "TimeSent", "AckNo", "timeACKed")
start = time.time()
seqno = 0
# Window size
N = 5
# How often to recalculate RTT, making sure it is greater than the window size
RTT_frequency = 300 + N
window_ack = []
for i in range(N):
window_ack.append(0)
tStart = time.time() # start counting here
# sending the first N in the window
for i in range (0, N):
body = datasource.wait_for_data(i)
# make a header, create a packet, and send it
hdr = bytearray(struct.pack(">II", magic, i))
pkt = hdr + body
tSend = time.time()
s.sendto(pkt, (host, port))
if verbose >= 3 or (verbose >= 1 and i < 5 or i % 1000 == 0):
print("Sent packet with seqno %d" % (i))
# initial timeout
timeout = 0.5
# intial starting time for probe packet
starting = time.time()
while seqno < 180000-N:
try:
s.settimeout(timeout)
(ack, reply_addr) = s.recvfrom(100)
#... message received in time, do something with the message ...
tRecv = time.time()
# unpack integers from the ACK packet, then print some messages
(magack, ackno) = struct.unpack(">II", ack)
if verbose >= 3 or (verbose >= 1 and seqno < 5 or seqno % 1000 == 0):
print("Got ack with seqno %d" % (ackno))
# if this is an ack for a probe packet, calculate how long it took
if ackno % RTT_frequency == 0 and ackno != 0:
total_time = time.time() - starting
timeout = (7/8)*timeout + (1/8)*total_time
# write info about the packet and the ACK to the log file
trace.write(seqno, tSend - start, ackno, tRecv - start)
# whatever ack that we received, record it
window_ack[ackno] = 1
# if this ack was the bottom of our window, move window up so that the bottom
# equals the lowest # ack we are waiting for
while window_ack[seqno] == 1:
# Send seqno + N
body = datasource.wait_for_data(seqno+N)
hdr = bytearray(struct.pack(">II", magic, seqno+N))
pkt = hdr + body
tSend = time.time()
# If this is a probe packet, start the timer
if (seqno+N) % RTT_frequency == 0 and seqno != 0:
starting = time.time()
s.sendto(pkt, (host, port))
if verbose >= 3 or (verbose >= 1 and seqno+N < 5 or seqno+N % 1000 == 0):
print("Sent packet with seqno %d" % (seqno+N))
# Shift up the end of the window
window_ack.append(0)
# Shift up beginning of window
seqno += 1
except (socket.timeout, socket.error):
#... no packets are ready to be received ...
if window_ack[seqno] == 0:
# get some example data to send
body = datasource.wait_for_data(seqno)
# if resending a probe packet, restart the timer
if seqno % RTT_frequency == 0 and seqno != 0:
starting = time.time()
# make a header, create a packet, and send it
hdr = bytearray(struct.pack(">II", magic, seqno))
pkt = hdr + body
tSend = time.time()
s.sendto(pkt, (host, port))
if verbose >= 3 or (verbose >= 1 and seqno < 5 or seqno % 1000 == 0):
print("Sent packet with seqno %d" % (seqno))
end = time.time()
elapsed = end - start
print("Finished sending all packets!")
print("Elapsed time: %0.4f s" % (elapsed))
trace.close()
if __name__ == "__main__":
if len(sys.argv) <= 2:
print("To send data to the server at 1.2.3.4 port 6000, try running:")
print(" python3 %s 1.2.3.4 6000" % (sys.argv[0]))
sys.exit(0)
host = sys.argv[1]
port = int(sys.argv[2])
main(host, port)