计算机网络原理实验三 :编程实现可靠数据传输原理Go-Back-N

实验三 编程实现可靠数据传输原理Go-Back-N

Go-Back-N 的有限状态机模型表示如图所示:

实验设置:

编程语言:python3

实验设置:

  1. 设置发送方和接收方
  2. 双方建立连接握手后,发送方向接收方发送多条数据

本实验中:

messages = '123,456,654,788,87364,875,8374'  # 可传输多条信息,每条信息以逗号隔开,每条信息分别依次发送

  1. 发送方向接收方传输数据时,按一定概率发生丢包,本实验设置丢包概率20%。(lost_probability = 0.2
  2. 设置接收方向发送方发送的回应不会丢失
  3. 对滑窗的第一个窗口,也就是最早发送的且没有ack的数据包设置时钟,计时到之后会重滑窗的所有数据包。
  4. 接收方采用累计确认方法

 实验文件结构:

 实验步骤:

Sender.py 关键代码:

发送消息:

# 尝试发送消息  
if(nextseqnum < base + window_size):  # 是否可以发送这个消息  
    # 发送消息  
    chksum_s = Mychecksum(str(nextseqnum) + message_list[nextseqnum-1])  
    sndpkt = str(nextseqnum) + ',' + message_list[nextseqnum-1] + ',' + chksum_s  # 打包数据nextseqnum,message,chksum  
    print('发送消息:', sndpkt)  
    conn.send(sndpkt.encode())  
    if base == nextseqnum:  # 发送的消息是滑窗的第一个窗口,开启计时  
        stop_timer = 0  
        pickle.dump(0, open('flag', 'wb'))  
        timer1 = threading.Thread(target=mytimer)  
        timer1.start()  
        print("开始计时")  
    message_flag[nextseqnum-1] = 1  # 发送过的消息相应的flag置为1  
    nextseqnum = nextseqnum + 1  
    time.sleep(1)   

接收响应:

# 接收消息
try:
    receive = conn.recv(1024).decode()
    if receive == 'Lost':  # 发生丢包,接收端没有收到消息,但发送端并不知道,因此不做任何动作
        has_receive = False
    else:
        has_receive = True
except:
    pass
if has_receive:  # 接收到接收端的回应
    print('接收消息:', receive)
    acknum, expectseqnum, chksum_r = receive.split(',')
    chksum_y = Mychecksum(acknum + expectseqnum)
    if chksum_r == chksum_y:  # 通过校验和校验
        base = int(acknum) + 1
        if base == nextseqnum:  # 滑窗第一个窗口接收到ack,计时停止
            stop_timer = 1
            print('结束计时')
        else:  # 代表接收端之前发送的的某个回应消息丢失了,但是由于是累计确认,仅需要开启新计时即可
            stop_timer = 0
            pickle.dump(0, open('flag', 'wb'))
            timer1 = threading.Thread(target=mytimer)
            timer1.start()
    time.sleep(1)

时钟:

# 检查定时器
time.sleep(1)
flag = pickle.load(open('flag', 'rb'))
print('检查定时器flag:', flag)
if(flag == 1):  # timeout 重新发送窗口中的所有包
    print('重新发送')
    nextseqnum = base
    for i in range(window_size):
        if base+i-1 < message_num:
            message_flag[base+i-1] = 0
time.sleep(1)
print()

Receiver.py 关键代码:

while True:
   f = random.random()  # 产生(0,1)之间的随机数
   
   # 模拟丢包
   if(f < lost_probability):
      rcvpkt = s.recv(1024).decode()
      seqnum, message, chksum_r = rcvpkt.split(',')
      if message == 'Message over':  # 是否传输完毕
         print(message)
         print('messages:', *message_list)
         print('Close')  # 传输完毕,关闭连接
         s.close()
         break
      print("Lost\n")
      s.send('Lost'.encode())  # 实际上丢包时,接收端并不会产生任何回应,此处仅为模拟丢包
      time.sleep(1)
   
   # 未丢包
   else:
      rcvpkt = s.recv(1024).decode()
      print('接收到的消息:', rcvpkt)
      seqnum, message, chksum_r = rcvpkt.split(',')
      chksum_y = Mychecksum(seqnum + message)
      if chksum_r == chksum_y:  # 校验和检验
         if int(seqnum) == expectseqnum:  # 检验收到的消息是否为期望的消息
      
            if message == 'Message over':  # 是否传输完毕
               print(message)
               print('\nmessages:', *message_list)
               print('Close')  # 传输完毕,关闭连接
               s.close()
               break
            
            expectseqnum = expectseqnum + 1
            ack = str(seqnum)
            print(f'ACK{ack}:{message}')  # 打印此次接收到的消息序号和消息内容
            message_list.append(message)  # 将此次消息放入消息组的列表中
            chksum_s = Mychecksum(ack + str(expectseqnum))  # 计算校验和
            sndpkt = ack + ',' + str(expectseqnum) + ',' + chksum_s  # 发送响应消息:已收到的消息序号,期望的下一消息序号,校验和
            print('发送消息:', sndpkt)
            s.send(sndpkt.encode())
         else:  # 收到的消息不是期望的消息
            s.send('Lost'.encode())
            print('Not expected seq')
      time.sleep(1)
      print()

实验结果:

发送端:

Hi Sender_Alice. Welcome to Chat Room
Initialising....
DESKTOP-BK14LMU ( IP )
Waiting for incoming connections...
Received connection from  IP ( 端口号 )
Receiver_Bob has connected to the chat room

发送消息: 1,123,0x9c9b  # 发送第1条消息
开始计时
接收消息: 1,2,0xcecd  # ack1
结束计时
检查定时器flag: 0

发送消息: 2,456,0x9895  # 发送第2条消息
开始计时
检查定时器flag: 0

发送消息: 3,654,0x9795  # 发送第3条消息
检查定时器flag: 0

发送消息: 4,788,0x9390  # 发送第4条消息
检查定时器flag: 1  # 在规定时间内,没有收到第2条消息的ack
重新发送

发送消息: 2,456,0x9895  # 重新发送的第2条消息
开始计时  # 重新计时
接收消息: 2,3,0xcdcc  # ack2
结束计时
检查定时器flag: 0

发送消息: 3,654,0x9795  # 重新发送的第3条消息
开始计时
检查定时器flag: 0

发送消息: 4,788,0x9390  # 重新发送的第4条消息
检查定时器flag: 0

发送消息: 5,87364,0x5d60  # 发送第五条消息
检查定时器flag: 1  # 在规定时间内,没有收到第3条消息的ack
重新发送

发送消息: 3,654,0x9795  # 重新发送第3条消息
开始计时
接收消息: 3,4,0xcccb  # ack3
结束计时
检查定时器flag: 0

发送消息: 4,788,0x9390  # 重新发送第4条消息
开始计时
接收消息: 4,5,0xcbca  # ack4
结束计时
检查定时器flag: 0

发送消息: 5,87364,0x5d60  # 重新发送的第5条消息
开始计时
检查定时器flag: 0

发送消息: 6,875,0x9292  # 发送第6条消息
检查定时器flag: 0

发送消息: 7,8374,0x9249  # 发送第7条消息
检查定时器flag: 1  # 在规定时间内,没有收到第5条消息的ack
重新发送

发送消息: 5,87364,0x5d60  # 重新发送的第5条消息
开始计时
接收消息: 5,6,0xcac9  # ack5
结束计时
检查定时器flag: 0

发送消息: 6,875,0x9292  # 重新发送的第6条消息
开始计时
接收消息: 6,7,0xc9c8  # ack6
结束计时
检查定时器flag: 0

发送消息: 7,8374,0x9249  # 重新发送的第7条消息
开始计时
接收消息: 7,8,0xc8c7  # ack7
结束计时
检查定时器flag: 0

Message over  # 消息已经全部发送成功,并接收方已全部接收
发送消息: 8,Message over,0xe97c
Close

接收端:

Hi Receiver_Bob. Welcome to Chat Room
Initialising....
Trying to connect to  IP ( 端口号 )
Connected...
Sender_Alice has joined the chat room

接收到的消息: 1,123,0x9c9b
ACK1:123
发送消息: 1,2,0xcecd

Lost  # 2号包丢失

接收到的消息: 3,654,0x9795
Not expected seq

接收到的消息: 4,788,0x9390
Not expected seq

接收到的消息: 2,456,0x9895  # 发送端重传了包2、3、4
ACK2:456
发送消息: 2,3,0xcdcc

Lost  # 3号包丢失

接收到的消息: 4,788,0x9390
Not expected seq

Lost  # 5号包丢失

接收到的消息: 3,654,0x9795  # 发送端重传了包3、4、5
ACK3:654
发送消息: 3,4,0xcccb

接收到的消息: 4,788,0x9390
ACK4:788
发送消息: 4,5,0xcbca

Lost  # 5号包丢失

接收到的消息: 6,875,0x9292
Not expected seq

Lost  # 7号包丢失

接收到的消息: 5,87364,0x5d60  # 发送端重传了包5、6、7
ACK5:87364
发送消息: 5,6,0xcac9

接收到的消息: 6,875,0x9292
ACK6:875
发送消息: 6,7,0xc9c8

接收到的消息: 7,8374,0x9249
ACK7:8374
发送消息: 7,8,0xc8c7

Message over
messages: 123 456 654 788 87364 875 8374
Close

完整代码见:https://download.csdn.net/download/llluuhp/87772153

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
基于 go-back-n 的可靠数据传输是一种常见的数据传输协议,它通过设置滑动窗口和确认号来实现可靠传输。要实现这样的软件,我们可以运用不同的编程语言进行开发。 首先,我们可以使用C语言进行开发。通过C语言的网络编程库,我们可以方便地实现基于 go-back-n 的数据传输软件。我们可以使用套接字来建立与远程主机的连接,并使用滑动窗口机制来控制数据的发送和接收。同时,使用C语言还可以轻松地管理缓冲区、序列号和确认号等变量。 其次,我们可以使用Java语言进行开发。Java提供了丰富的网络编程库,例如Socket和DatagramSocket类,可以方便地进行网络通信。通过使用Java的多线程机制,我们可以同时发送和接收数据,实现并行传输。同时,Java的面向对象特性可以让我们更好地设计和实现滑动窗口、帧结构和数据包的处理。 另外,我们还可以使用Python语言进行开发。Python是一种简洁而强大的脚本语言,具有易于理解和编写的特点。通过使用Python的套接字库,我们可以快速实现基于 go-back-n 的数据传输软件。此外,Python还提供了多线程和异步编程的支持,可以进一步提高软件的性能和效率。 总之,无论选择哪种编程语言进行开发,实现基于 go-back-n 的可靠数据传输软件需要注意的关键点包括:建立连接、设置滑动窗口大小、处理超时和丢包、发送和接收确认以及处理丢失数据或重复数据等情况。在实现过程中,我们需要仔细考虑各种操作系统和网络环境下的稳定性和可靠性,并进行适当的错误处理和异常处理,确保数据传输可靠性和完整性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

枫寒寒寒

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值