GBN和路由算法实验报告 计算机网络实验报告 ----GBN和路由算法 姓名:房皓 学号:13410801 教师:尹辉
GBN模拟实验 1. 实验目的 运用java编程语言实现基于Go-Back-N的可靠数据传输软件。 2. 实验意义 通过本实验,使学生能够对可靠数据传输原理有进一步的理解和掌握。 3. 实验背景 Go-Back-N的有限状态机模型表示如下图所示:
(a) GBN和路由算法实验报告 (b) 图为Go-Back-N的有限状态机模型(a)发送端 (b)接受端 4. 实验步骤
(1) 选择java编程语言编程实现基于Go-Back-N的可靠数据传输软件。 (2) 在实际网络环境或模拟不可靠网络环境中测试和验证自己的可靠数据传输软件。 5. 实验环境 (1) 实验语言:JAVA (2) 实验平台:Eclipse (3) 引用库函数:随机(Random)库、计时库(Timer) 6. 类概览与描述 (1) Sender类:继承于Thread(线程)类,模拟发送方的 一切功能,主要功能函数有: A. Public void run()——启动函数,标识开始发送数据包 B. Sender()——构造函数,分配并初始化窗口值 C. Public void getack(in tack)——ACK接收函数,接收接收方返回的ACK并进行验证是否为期待的ACK值(若不是,则重发) GBN和路由算法实验报告 D. Public void time()——定时器函数,初始化定时,计时并记录超时与否的状态 (2) Receiver类:继承于Thread(线程)类,模拟接收方的一切功能,主要功能函数有: A. Public void run()——启动函数,标识开始等待并接收数据包 B. Void Receive(int data,Sender s)——数据包接收函数,功能强大!主要包括:接收数据包,验证数据包,判断与丢弃数据包,发送ack等 (3) Timers类:继承于TimerTask(计时器)类,具有自定义定时与超时提醒的功能,主要功能函数有: A. Public void run()——启动函数,标识开始计时(这里预设的是2秒的时间),超时后提醒并且停止计时器 B. Public Timers()——构造函数,清0计时器,等待下一次启动
(4) GBN类:继承于Thread(线程)类,是主函数类,具有本程序的核心功能,这里先作一部分简单介绍,主要函数功能有: A. Static void senddelay(int x) throws InterruptedExceptionPublic Timers()——随机延GBN和路由算法实验报告 迟函数,模拟数据包发送传输过程中的随机延迟,常用延迟值分别为:300ms, 750ms, 1200ms, 3000ms等 B. Public static void main(String[] args) throws IOException, InterruptedException()——主函数,功能强大,主要包含以下几大方面: ① 开启发送端与接收端(包括计时器) ② 超时或者ACK不匹配等情况导致的发送方 重新发送数据包 ③ (第一次)发送当前窗口内的数据包 ④ 随机函数模拟数据包发送过程中的丢包情况 ⑤ 实时更新与显示当前窗口内的数据包情况 ⑥ 统计每一个数据包被发送过的次数(含重发)并最终显示出来 C. static void OutputWindow(Sender s) ——输出当前窗口状态函数。 7. 代码展示与描述 (一) Sender类 import java.util.Timer; public class Sender extends Thread{ public int windowsize=4; //发送方窗口长度设为3 public String[] data={"data1","data2","data3", GBN和路由算法实验报告 "data4","data5","data6","data7"}; //模拟七个数据包 public int sign[]={0,1,2,3,4,5,6}; //为7个数据包标号 public int localack=-1; //保存最近收到的ACK public Timers litime=null; //定时器(这里定为2秒) public int switches=0; //超时标志,1为超时 public int windowsign[]; //当前窗口内待发的数据分组的序号 public int acksign[]={1,1,1,1,1,1,1}; //为0表示收到正确ACK,为1表示收到错误的ACK,必须重发! public int sent[]={1,1,1,1,1,1,1};//发送标记,1未发送,0已发送 public int acknowledged[]={1,1,1,1,1,1,1};//接收标记,1未接收,0已接收 public Sender(){ windowsign=new int[windowsize]; //给窗口分配指定大小的空间 for(int i=0;iwindowsign[i]=sign[i]; //窗口初始化时存放前3个序号 } public void run(){ System.out.println("发送方:现在开始发送分组数据!"); } public void getack(int ack){ System.out.println("发送方:收到了ACK,序号为"+ack+",现在开始确认!"); if(ack!=localack+1){ System.out.println("发送方:经验证,这不是发送方正期待的ACK,即将重发序号为"+(localack+1)+"的数据分组!"); //acksign[localack+1]=1; } else{ localack=ack; //表示正确确认了ACK acksign[localack]=0; } } public void time(){ switches=0; //标志初始化为0 litime=new Timers(); Timer limit=new Timer(); limit.schedule(litime, 0,100); } }
(二) Receiver类
import java.util.Random; public class Receiver extends Thread{ public int lastdata=-1; GBN和路由算法实验报告 public int expectdata; public Sender sender; public void run(Sender s){ sender=s; System.out.println("接收方:现在接收分组数据!"); } void receive(int data, Sender s){ sender=s; //发送方的参数传递 System.out.println("接收方:收到了序号为"+data+"的分组!");
if(data==lastdata+1){ //数据包序号校验,若连续则是正确/所期待的 System.out.println("接收方:该数据分组正是所期待的,接受它并准备回送对应的ACK!"); if(sender.litime.limit<20){ //判断是否超时(2秒) lastdata++; //更新本地保存的数据包序号变量 //ack=lastdata; //获取本场保存的数据包序号 sender.getack(lastdata); } else{ expectdata=lastdata+1; System.out.println("发送方:计时超时!!(未丢包但是时间超过2秒)即将重发序号为"+expectdata+"的数据分组!"); //sender.acksign[lastdata+1]=1; sender.switches=1; //如果超时,设置超时状态并显示警告 } //lastdata=data; //更新本地保存的数据包序号变量 //respond(lastdata+1); //回送该正确接收的数据包对应的ACK } else{ System.out.println("接收方:该数据分组不是接收方所期待的,该分组将被丢弃,接收方准备回送最后接受的数据分组对应的ACK!"); //respond(lastdata); //若不是所期待的数据包则丢弃并且重发上一次的ACK if(sender.litime.limit<20){ //判断是否超时(2秒) sender.getack(lastdata); } else{ expectdata=lastdata+1; System.out.println("发送方:计时超时!!(未丢包但是时间超过2秒)发送方即将重发序号为"+expectdata+"的数据分组!"); sender.switches=1; //如果超时,设置超时状态并显