Assignment|GoBackN的python实现

看起来非常简略的gbn的python实现

GBN介绍

GBN的有限状态机模型

代码

客户端

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
import socket
import threading

LENGTH = 3 # 数据总长度


def timeout():
print('timeout!')

timer.cancel()

if end_ack != LENGTH - 1:
Resend(end_ack)
timer1 = threading.Timer(5, timeout)
timer1.start()
else:
print("数据全部发送成功")


def Resend(EndAck):
# 发端重传ack
print('发端重传数据包%d--%d' % (EndAck + 1, LENGTH - 1))
for a in range(EndAck + 1, LENGTH):
RSendData = bin(a)
print('发端重传数据%d' % a)
ReceiveSocket.sendto(RSendData.encode('utf-8'), ('127.0.0.1', 9999))


timer = threading.Timer(5, timeout) # 设置定时器
# 创建socket
ReceiveSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

# 发送数据包0,1,2
for data in range(0, LENGTH):
sendData = bin(data)
print('发端发送数据%d' % data)
ReceiveSocket.sendto(sendData.encode('utf-8'), ('127.0.0.1', 9999))

timer.start()

while True:
# 接收收端发回的ack
ack_seq = ReceiveSocket.recv(1024)
print("发端接收ack%d" % int(ack_seq, 2))
end_ack = 0
end_ack = max(end_ack, int(ack_seq, 2))

服务端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import socket
import random

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind(('127.0.0.1', 9999))
print("waiting for connection...")
HadReceive = 0
while True:
ReceiveData, ReceiveAddress = s.recvfrom(1024)
seq = int(ReceiveData, 2)
# 用一个随机数来模拟丢包的情况,丢包概率为0.3
if random.uniform(0, 1) <= 0.7:
# 没有丢包,向发端发送ack
if seq == HadReceive + 1:
HadReceive = HadReceive + 1
print('收端发送ack%d' % HadReceive)
AckData = bin(HadReceive)
s.sendto(AckData.encode('utf-8'), ReceiveAddress)
else:
print('数据包%d丢失!' % seq)

测试

在实际网络环境或模拟不可靠网络环境中测试和验证自己的可靠数据传输软件。我在Server端采用随机数的方式模拟不可靠的网络环境,随机数(0,1)小于0.3则模拟发生丢包。采用三个包的测试,测试五次。情况如下:

第一次:

发端发送数据0

发端发送数据1

发端发送数据2

发端接收ack0

发端接收ack1

发端接收ack2

数据全部发送成功

第二次:

发端发送数据0

发端发送数据1

发端发送数据2

发端接收ack0

timeout!

发端重传数据包1–2

发端重传数据1

发端重传数据2

发端接收ack1

发端接收ack2

timeout!

数据全部发送成功

第三次:

发端发送数据0

发端发送数据1

发端发送数据2

发端接收ack0

发端接收ack0

timeout!

发端重传数据包1–2

发端重传数据1

发端重传数据2

发端接收ack1

发端接收ack2

timeout!

数据全部发送成功

第四次:

发端发送数据0

发端发送数据1

发端发送数据2

发端接收ack1

timeout!

发端重传数据包2–2

发端重传数据2

发端接收ack2

timeout!

数据全部发送成功

第五次:

发端发送数据0

发端发送数据1

发端发送数据2

发端接收ack0

timeout!

发端重传数据包1–2

发端重传数据1

发端重传数据2

发端接收ack1

发端接收ack2

timeout!

数据全部发送成功

结论:

通过编写GBN算法,可以加强对课上的内容的理解,要注意的是在模拟丢包的情况下,要在接收端阻止ack的回传和在发送端发现ack超时的情况下进行该包的重发,要注意整个包的传送组织结构和顺序;进行模拟时,注意标注丢包及正确收到的flag值。同时可以通过多次实验来判断编写的算法是否满足GBN的要求。