看起来非常简略的gbn的python实现
GBN介绍
![GBN的有限状态机模型](https://pic-aus-1252275196.cos.ap-nanjing.myqcloud.com/img/20211223/123.png)
代码
客户端
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): 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)
ReceiveSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
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_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) if random.uniform(0, 1) <= 0.7: 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则模拟发生丢包。采用三个包的测试,测试五次。情况如下:
![](https://pic-aus-1252275196.cos.ap-nanjing.myqcloud.com/img/20211223/1.png)
第一次:
发端发送数据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的要求。