计算机网络实验报告(三)——编程实现可靠数据传输原理GO-BACK-N(一)实验目的:运用各种编程语言实现基于Go-Back-N的可靠数据传输软件。通过本实验,使学生能够对可靠数据传输原理有进一步的理解和掌握。(二)实验内容:(1).选择合适的编程语言编程实现基于Go-Back-N的可靠数据传输软件。(2).在实际网络环境或模拟不可靠网络环境中测试和验证自己的可靠数据传输软件。(三)实验原理:1.GBN协议含义:Go-Back-NARQ中文翻译为后退N式ARQ、回退N式ARQ。该协议对传统的自动重传请求(ARQ,AutomaticRepeatreQues)进行了改进,从而实现了在接收到ACK之前能够连续发送多个数据包。在Go-Back-NARQ中,发送端不需要在接收到上一个数据包的ACK后才发送下一个数据包,而是可以连续发送数据包。在发送端发送数据包的过程中,如果接收到对应已发送的某个数据包的NACK,则发送端将NACK对应的某个数据包进行重发,然后再将该数据包之后的数据包依次进行重发。后退N帧ARQ的图例:后退N帧ARQ就是从出错处重发已发出过的N个帧。2.Go-Back-N的有限状态机模型表示如图所示:(a)(b)图3.1Go-Back-N的有限状态机模型(a)发送端(b)接受端(四)实验步骤:在eclipse平台编写并调试GBN模拟java程序,观察三组以上实验结果,验证程序可以正确模拟GBN的发送规则。(五)实验结果:以下为随机数模拟的某次发送情况:接收方开始接收分组数据!发送方开始发送分组数据!发送方现在开始第一次发送序号为0的数据分组当前窗口内的分组情况为:第0号窗口里面存放的是序号为1的马上待发送的数据分组!第1号窗口里面存放的是序号为2的马上待发送的数据分组!第2号窗口里面存放的是序号为3的马上待发送的数据分组!接收方收到了序号为0的分组!该数据分组正是接收方所期待的,接收方接受了它并准备回送对应的ACK!发送方收到了ACK,序号为0并且开始加以确认!发送方现在开始第一次发送序号为1的数据分组当前窗口内的分组情况为:第0号窗口里面存放的是序号为2的马上待发送的数据分组!第1号窗口里面存放的是序号为3的马上待发送的数据分组!第2号窗口里面存放的是序号为4的马上待发送的数据分组!发送数据分组时发生延迟:1200毫秒!接收方收到了序号为1的分组!该数据分组正是接收方所期待的,接收方接受了它并准备回送对应的ACK!发送方收到了ACK,序号为1并且开始加以确认!发送方现在开始第一次发送序号为2的数据分组当前窗口内的分组情况为:第0号窗口里面存放的是序号为3的马上待发送的数据分组!第1号窗口里面存放的是序号为4的马上待发送的数据分组!第2号窗口里面存放的是序号为5的马上待发送的数据分组!发送数据分组时发生延迟:750毫秒!序号为2的分组在传给接收方途中发生了丢包!发送方开始重新发送序号为2的数据分组发送数据分组时发生延迟:750毫秒!接收方收到了序号为2的分组!该数据分组正是接收方所期待的,接收方接受了它并准备回送对应的ACK!发送方收到了ACK,序号为2并且开始加以确认!发送方现在开始第一次发送序号为3的数据分组当前窗口内的分组情况为:第0号窗口里面存放的是序号为4的马上待发送的数据分组!第1号窗口里面存放的是序号为5的马上待发送的数据分组!第2号窗口里面存放的是序号为6的马上待发送的数据分组!发送数据分组时发生延迟:300毫秒!接收方收到了序号为3的分组!该数据分组正是接收方所期待的,接收方接受了它并准备回送对应的ACK!发送方收到了ACK,序号为3并且开始加以确认!发送方现在开始第一次发送序号为4的数据分组当前窗口内的分组情况为:第0号窗口里面存放的是序号为5的马上待发送的数据分组!第1号窗口里面存放的是序号为6的马上待发送的数据分组!第2号窗口已经空了,并且后续窗口、发送方没有要发送的数据分组了!发送数据分组时发生延迟:750毫秒!接收方收到了序号为4的分组!该数据分组正是接收方所期待的,接收方接受了它并准备回送对应的ACK!发送方收到了ACK,序号为4并且开始加以确认!发送方现在开始第一次发送序号为5的数据分组当前窗口内的分组情况为:第0号窗口里面存放的是序号为6的马上待发送的数据分组!第1号窗口已经空了,并且后续窗口、发送方没有要发送的数据分组了!第2号窗口已经空了,并且后续窗口、发送方没有要发送的数据分组了!发送数据分组时发生延迟:1200毫秒!序号为5的分组在传给接收方途中发生了丢包!发送方开始重新发送序号为5的数据分组序号为5的分组在传给接收方途中发生了丢包!发送方开始重新发送序号为5的数据分组发送数据分组时发生延迟:1200毫秒!接收方收到了序号为5的分组!该数据分组正是接收方所期待的,接收方接受了它并准备回送对应的ACK!发送方收到了ACK,序号为5并且开始加以确认!发送方现在开始第一次发送序号为6的数据分组当前窗口内的分组情况为:第0号窗口已经空了,并且后续窗口、发送方没有要发送的数据分组了!第1号窗口已经空了,并且后续窗口、发送方没有要发送的数据分组了!第2号窗口已经空了,并且后续窗口、发送方没有要发送的数据分组了!发送数据分组时发生延迟:750毫秒!序号为6的分组在传给接收方途中发生了丢包!发送方开始重新发送序号为6的数据分组发送数据分组时发生延迟:3000毫秒!序号为6的分组在传给接收方途中发生了丢包!发送方开始重新发送序号为6的数据分组发送数据分组时发生延迟:3000毫秒!接收方收到了序号为6的分组!该数据分组正是接收方所期待的,接收方接受了它并准备回送对应的ACK!计时超时!!(未丢包但是时间超过2秒)发送方准备重发序号为6的数据分组!发送方开始重新发送序号为6的数据分组发送数据分组时发生延迟:750毫秒!接收方收到了序号为6的分组!该数据分组不是接收方所期待的,该分组将被丢弃,接收方准备回送最后接受的数据分组对应的ACK!发送方收到了ACK,序号为6并且开始加以确认!当前窗口内的分组情况为:第0号窗口已经空了,并且后续窗口、发送方没有要发送的数据分组了!第1号窗口已经空了,并且后续窗口、发送方没有要发送的数据分组了!第2号窗口已经空了,并且后续窗口、发送方没有要发送的数据分组了!发送数据分组时发生延迟:300毫秒!序号为7的分组在传给接收方途中发生了丢包!以下是每个数据分组被发送过的次数的统计结果序号为0的数据分组被发送过的次数为:1序号为1的数据分组被发送过的次数为:1序号为2的数据分组被发送过的次数为:2序号为3的数据分组被发送过的次数为:1序号为4的数据分组被发送过的次数为:1序号为5的数据分组被发送过的次数为:3序号为6的数据分组被发送过的次数为:4(六)问题总结:1.编写GBN算法,要注意的是在模拟丢包的情况下,要在接收端阻止ack的回传和在发送端发现ack超时的情况下进行该包的重发,要注意整个7个包的传送组织结构和顺序;2.进行模拟时,注意标注丢包及正确收到的flag值;3.测试时应多运行几次,观察在各种随机传送情况下的总体的发送情况,来验证是否能满足GBN协议。(七)附录:java源代码:【GBN.java】importjava.net.*;importjava.util.Random;importjava.io.*;publicclassGBNextendsThread{staticvoidsenddelay(intx)throwsInterruptedException{if(x==1){sleep(300);System.out.println(发送数据分组时发生延迟:300毫秒!);}elseif(x==2){sleep(750);System.out.println(发送数据分组时发生延迟:750毫秒!);}elseif(x==3){sleep(1200);System.out.println(发送数据分组时发生延迟:1200毫秒!);}elseif(x==4){sleep(3000);System.out.println(发送数据分组时发生延迟:3000毫秒!);}else;}publicstaticvoidmain(String[]args)throwsIOException,InterruptedException{Senders=newSender();Receiverre=newReceiver();s.start();re.run(s);//发送端启动//接收端启动//延迟处理sleep(1000);int[]retimes=newint[7];//计算每个分组被发送的次数for(inti=0;i7;i++)retimes[i]=0;for(inti=0;i=s.sign.length;i++){while(is.localack+1){//数据包顺次发送//尚有未确认的数据包,重发!System.out.println(发送方开始重新发送序号为+(s.localack+1)+的数据分组);retimes[s.localack+1]++;intran=newRandom().nextInt(3);intrandelay=newRandom().nextInt(5);s.time();senddelay(randelay);//设置随机值,模拟数据传输延迟if(ran!=1)re.receive(s.localack+1,s);//设置随机值,模拟数据丢包过程elseSystem.out.println(序号为+(s.localack+1)+的分组在传给接收方途中发生了丢包!);}if(i!=s.sign.length){System.out.println();System.out.println(发送方现在开始第一次发送序号为+i+的数据分组);retimes[i]++;for(intk=0;k3;k++){s.windowsign[k]++;}}System.out.println();System.out.println(当前窗口内的分组情况为:);for(intp=0;p3;p++){if(s.windowsign[p]=6)System.out.println(第+p+号窗口里面存放的是序号为+s.windowsign[p]+的马上待发送的数据分组!);elseSystem.out.println(第+p+号窗口已经空了,并且后续窗口、发送方没有要发送的数据分组了!);}System.out.println();intran=newRandom().nextInt(3);intrandelay=newRandom().nextInt(5);s.time();//计时开始(2秒时间)senddelay(randelay);if(ran!=1)re.receive(s.sign[i],s);elseSystem.out.println(序号为+i+的分组在传给接收方途中发生了丢包!);}System.out.println();System.out.println(以下是每个数据分组被发送过的次数的统计结果);for(inti=0;i7;i++)//显示关于每个数据包发送次数的统计表System.out.println(序号为+i+的数据分组被发送过的次数为:+retimes[i]);System.exit(0);}}【Receiver.java】publicclassReceiverextendsThread{publicintlastdata;publicSendersender;publicvoidrun(Senders){sender=s;System.out.println(接收方开始接收分组数据!);}voidreceive(intdata,Senders){sender=s;//发送方的参数传递System.out.println(接收方收到了序号为+data+的分组!);if(data!=0){if