计算机网络实验报告
----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}; public int localack=-1; public int switches=0;
public Timers litime=null; public int windowsign[];
//为7个数据包标号 //保存最近收到的ACK
//定时器(这里定为2秒) //超时标志,1为超时
//当前窗口内待发的数据分组的序号
public int acksign[]={1,1,1,1,1,1,1}; //为0表示收到正确ACK,为1表示收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(){
到错误的ACK,必须重发!
windowsign=new int[windowsize]; for(int i=0;i public void getack(int ack){ } public void time(){ } switches=0; //标志初始化为0 litime=new Timers(); Timer limit=new Timer(); limit.schedule(litime, 0,100); System.out.println(\"发送方:收到了ACK,序号为\"+ack+\",现在开始确认!if(ack!=localack+1){ } else{ } localack=ack; //表示正确确认了ACK acksign[localack]=0; System.out.println(\"发送方:经验证,这不是发送方正期待的ACK,即//acksign[localack+1]=1; System.out.println(\"发送方:现在开始发送分组数据!\"); windowsign[i]=sign[i]; //窗口初始化时存放前3个序号 //给窗口分配指定大小的空间 \"); 将重发序号为\"+(localack+1)+\"的数据分组!\"); (二) 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){ } void receive(int data, Sender s){ sender=s; if(data==lastdata+1){ } else{ System.out.println(\"接收方:该数据分组不是接收方所期待的,该//respond(lastdata); } else{ expectdata=lastdata+1; System.out.println(\"发送方:计时超时!!(未丢包但是时间sender.switches=1; //如果超时,设置超时状态并显 //数据包序号校验,若连续则是正确/所期待的 System.out.println(\"接收方:该数据分组正是所期待的,接受它并if(sender.litime.limit<20){ } else{ } //lastdata=data; //更新本地保存的数据包序号变量 //respond(lastdata+1); //回送该正确接收的数据包对应的ACK expectdata=lastdata+1; System.out.println(\"发送方:计时超时!!(未丢包但是时间//sender.acksign[lastdata+1]=1; sender.switches=1; //如果超时,设置超时状态并显 lastdata++; //判断是否超时(2秒) //更新本地保存的数据包序 //发送方的参数传递 System.out.println(\"接收方:收到了序号为\"+data+\"的分组!\"); sender=s; System.out.println(\"接收方:现在接收分组数据!\"); 准备回送对应的ACK!\"); 号变量 //ack=lastdata; //获取本场保存的数据包序号 sender.getack(lastdata); 超过2秒)即将重发序号为\"+expectdata+\"的数据分组!\"); 示警告 分组将被丢弃,接收方准备回送最后接受的数据分组对应的ACK!\"); //若不是所期待的数据包则丢弃并且重发上一次的ACK //判断是否超时(2秒) sender.getack(lastdata); if(sender.litime.limit<20){ 超过2秒)发送方即将重发序号为\"+expectdata+\"的数据分组!\"); GBN和路由算法实验报告 示警告 } } } } (三) Timers类 import java.util.TimerTask; public class Timers extends TimerTask { } public int switches; public int limit; public void run(){ } public Timers(){ } System.out.println(\"发送方:现在开始计时\"); switches=0; limit=0; //启动计时器时全部初始化 if(limit<20) limit++; else { } switches=-1; this.cancel(); //开关为-1表示超时,并且停止计时器 //计时2秒 (四) GBN类 import java.net.*; import java.util.Random; import java.io.*; public class GBN extends Thread{ static void senddelay(int x,int y) throws InterruptedException{ if(x==1) {sleep(300); System.out.println(\"发送数据分组\"+y+\"时发生延迟:300毫秒!\"); } else if(x==2) {sleep(750); System.out.println(\"发送数据分组\"+y+\"时发生延迟:750毫秒!\");} else if(x==3) {sleep(1200);System.out.println(\"发送数据分组\"+y+\"时发生延迟:1200毫秒!\");} else if(x==4) {sleep(2500);System.out.println(\"发送数据分组\"+y+\"时发生延迟:2500毫秒!\");} else if(x==5) {sleep(3000);System.out.println(\"发送数据分组\"+y+\"时发生延迟:3000毫秒!\");} GBN和路由算法实验报告 else; } // } //表示至少成功发送并确认了一个数据分组 static void OutputWindow(Sender s){ for(int k=0;k //这种情况下滑动窗口向前移动! System.out.println(); System.out.println(\"当前窗口内的分组情况为:\"); 显示当前窗口内数据包情况 for(int p=0;p public static void main(String[] args) throws IOException, InterruptedException { Sender s=new Sender(); Receiver re=new Receiver(); s.start(); re.run(s); sleep(1000); //发送端启动 //接收端启动 //延迟处理 if(s.windowsign[p]<=6) if(s.sent[s.windowsign[p]]==0 ){ } else System.out.println(\"第\"+p+\"号窗口里面存放的是序号为System.out.println(\"第\"+p+\"号窗口里面存放的是序号为 \"+s.windowsign[p]+\"的待确认的数据分组!\"); \"+s.windowsign[p]+\"的待发送的数据分组!\"); else System.out.println(\"第\"+p+\"号窗口已经空了,并且后续窗口、发送方没有要发送 的数据分组了!\"); //int[] retimes=new int[7]; //for(int i=0;i<7;i++) retimes[i]=0; for(int i=0;i<=s.sign.length;){ while(i>s.localack+1){ //尚有未确认的数据包,重发! System.out.println(\"发送方:现在发送序号为//retimes[s.localack+1]++; int ran=new Random().nextInt(4); //数据包顺次发送 //计算每个分组被发送的次数 \"+(s.localack+1)+\"的数据分组\"); GBN和路由算法实验报告 } int randelay=new Random().nextInt(6); s.time(); senddelay(randelay,s.localack+1); //设置随机值,模拟数据传if(ran!=1) { } else System.out.println(\"序号为\"+(s.localack+1)+\"的分组在 re.receive(s.localack+1,s); if(s.localack>=0) if(s.acksign[s.localack]==0) { } if(s.localack+3<=6) s.sent[s.localack+3]=0; OutputWindow(s); //设置随机值,模拟数据丢包过程 输延迟 传给接收方途中发生了丢包!\"); if(i!=s.sign.length){ if(i==0){ System.out.println(); System.out.println(\"发送方:现在发送序号为0~2的数据分组s.sent[0]=0; s.sent[1]=0; s.sent[2]=0; System.out.println(); int ran1=new Random().nextInt(4); int randelay1=new Random().nextInt(6); s.time(); \"); //计时开始(2秒时间) //设置随机值,模拟数据传 senddelay(randelay1,0); if(ran1!=1) { } 输延迟 re.receive(s.sign[0],s); if(s.acksign[0]==0) { } s.sent[3]=0; s.acknowledged[0]=0; OutputWindow(s); //设置随机值,模拟数据丢包过程 else System.out.println(\"序号为\"+\"0\"+\"的分组在传给接收 方途中发生了丢包!\"); GBN和路由算法实验报告 i++; //retimes[0]++; int ran2=new Random().nextInt(4); int randelay2=new Random().nextInt(6); s.time(); //计时开始(2秒时间) //设置随机值,模拟数据传 senddelay(randelay2,1); if(ran2!=1) { } 输延迟 re.receive(s.sign[1],s); if(s.acksign[1]==0) { } s.sent[4]=0; //retimes[4]++; s.acknowledged[1]=0; OutputWindow(s); //设置随机值,模拟数据丢包过程 else System.out.println(\"序号为\"+\"1\"+\"的分组在传给接收 i++; //retimes[1]++; int ran3=new Random().nextInt(4); int randelay3=new Random().nextInt(6); s.time(); 方途中发生了丢包!\"); //计时开始(2秒时间) //设置随机值,模拟数据传 senddelay(randelay3,2); if(ran3!=1) { } 输延迟 re.receive(s.sign[2],s); if(s.acksign[2]==0) { } s.sent[5]=0; //retimes[5]++; s.acknowledged[2]=0; OutputWindow(s); //设置随机值,模拟数据丢包过程 else System.out.println(\"序号为\"+\"2\"+\"的分组在传给接收i++; //retimes[2]++; 方途中发生了丢包!\"); GBN和路由算法实验报告 } } } } } else{ System.out.println(); if(s.sent[i]==0){ } else System.out.println(\"发送方:现在发送序号为\"+i+\"的数据分组\"); int ran=new Random().nextInt(4); int randelay=new Random().nextInt(6); s.time(); if(ran!=1) { } else System.out.println(\"序号为\"+i+\"的分组在传给接收方途中//System.out.println(\"i==\"+i); //System.out.println(\"s.localack\"+s.localack); i++; re.receive(s.sign[i],s);//设置随机值,模拟数据丢包过程 if(s.acksign[i]==0) { } if(i+3<=6){ } s.acknowledged[i]=0; OutputWindow(s); s.sent[i+3]=0; //System.out.println(\"发送方现在发送序号为 senddelay(randelay,i); //计时开始(2秒时间) System.out.println(\"发送方:现在发送序号为\"+i+\"的数据分 组\"); //设置随机值,模拟数据传输延迟 \"+(i+3)+\"的数据分组\"); 发生了丢包!\"); else break; /*System.out.println();System.out.println(\"以下是每个数据分组被发for(int i=0;i<7;i++) //显示关于每个数据包发送次数的统计表 送过的次数的统计结果\"); System.out.println(\"序号为\"+i+\"的数据分组被发送过的次数为: System.out.println(\"全部数据发送完毕!\"); System.exit(0); \"+retimes[i]);*/ GBN和路由算法实验报告 } 8. 程序运行结果部分截图 GBN和路由算法实验报告 GBN和路由算法实验报告 GBN和路由算法实验报告 路由算法实验 1. 实验目的 1. 深入理解分布式路由选择算法,以最简单的DV算法来增 强对路由算法的认识 2. 理解、掌握和利用距离向量算法 3. 所实现的路由器模拟Internet上的IP路由器。它能确定 网络的最短路由,并在这些利用上传输分组。 2. 实验意义 通过本实验,使学生能够对路由原理和路由算法有进一步的理解和掌握。 3. 实验背景 距离矢量算法,也称为Bellman-Ford shortest path algorithm,每个路由器都定期或拓扑结构突发变化时与其相邻的所有路由器交换路由表,据此更新它们自己的路由表。 DV算法工作方式:每个路由器维护一张路由表,表中分为三个表项:目的地址,列出了当前可达的目的网络地址;到达目的地址下一跳,列出了下一跳的IP地址;到达目的地址的代价,以距离或跳数为表征。 路由表更新规则: 1.发现了一条到达某目的的新路由,而该路由在原来的路 由表中不存在(即发现了一条新路由),则在路由表中增加该路由。 2.发现了一条到达某目的的、距离更短的新路由,则用该 路由替换原有的路由。 3.到达某目的的一条路由,其后继结点到达该目的地的距 离发生了变化,则需要更新该路由的距离。 4. 实验步骤 GBN和路由算法实验报告 选择C编程语言编程实现DV(距离矢量)路由算法 5. 实验环境 (1)实验语言:C (2)实验平台:VC++6.0 (3)引用头文件:stdio.h、stdlib.h、conio.h 6. 函数概览与描述 (1) void InitData(FILE* pfile) 主要功能:从文件中读取路由表的初始信息 (2) void OutputRoutData() 主要功能:打印路由表 (3) void Communication(int recv, int send) 主要功能:向邻近节点发送自己的路由表信息 (4) void Exchange() 主要功能:根据新路由表信息更新自己的路由表 (5) void main() 主要功能:调用以上函数,完成程序 7. 代码展示与描述 (一)数据结构定义 typedef struct { int dis; //记录距离 int from; //记录中间节点 GBN和路由算法实验报告 }RoutNode; (二)void InitData(FILE* pfile)函数 void InitData(FILE* pfile) { char num[10]; int i = 0; char c; int m, n; fseek(pfile, 0, 0); { } } for (n = 0; !feof(pfile) && n < ROUTNUM; n++) { } while (!feof(pfile)) { } c = fgetc(pfile); if (c == ',') { } else if ((c >= '0' && c <= '9') || c == '-') { } num[i++] = c; num[i] = '\\0'; //添加字符串结束标志 //字符串转换成整型 data[m][n].dis = atoi(num); i = 0; break; //准备读取下一个数 //定位到文件头 for (m = 0; !feof(pfile) && m < ROUTNUM; m++) data[m][n].from = -1; //没有中间节点 (三)void OutputRoutData()函数 void OutputRoutData() { int i, j; printf(\" \"); for (i = 0; i < ROUTNUM; i++) { } printf(\"\\n\"); printf(\" %c \ //打印路由表 GBN和路由算法实验报告 for (i = 0; i < ROUTNUM; i++) { } } printf(\"%c \for (j = 0; j < ROUTNUM; j++) { } printf(\"\\n\"); if (data[i][j].dis < 0) else else printf(\" %c \if(data[i][j].dis > 10 || data[i][j].dis == 10) else printf(\" %d\printf(\" %d\printf(\" -\"); if (data[i][j].from < 0) printf(\" - \"); (四)void Communication(int recv, int send)函数 void Communication(int recv, int send) //信息交换,recv信息接收方,send信息发送方 { int i; for (i = 0; i < ROUTNUM; i++) { } if (data[send][i].dis > 0) { } if (data[recv][i].dis < 0) { } else if (data[recv][i].dis > data[send][i].dis + data[recv][send].dis)//接 { } data[recv][i].dis = data[send][i].dis + data[recv][send].dis; data[recv][i].from = send; data[recv][i].dis = data[send][i].dis + data[recv][send].dis; //更data[recv][i].from = send; //记录中间节点 //接收方到i节点没路径 //发送方到i节点有路径 改接收方到i节点的路径信息 收方到i节点有路径,但较大,一下两步是更新操作 GBN和路由算法实验报告 } (五)void Exchange()函数 void Exchange() { } int i, j; for (i = 0; i < ROUTNUM; i++) { } for (j = 0; j < ROUTNUM; j++) { } if (data[i][j].dis > 0 && data[i][j].from < 0 ) { } Communication(j, i); //更新路由表 (六)void main()函数 void main() { int start, end, i, j; FILE *pfile; pfile = fopen(\"1.txt\ if (pfile == NULL)//文件不存在,错误 { } else InitData(pfile);//读取路由表信息 fclose(pfile); printf(\"\\n路由表初始:\\n\"); //OutputRoutData(); for (i = 0; i for (j = 0; j < ROUTNUM; j++) if (data[i][j].dis > 0 )//|| data[i][j].dis == 0 //if(data[i][j].dis > 9) // printf(\"<%c %d> \printf(\"<%c %d> \//else //打印初始的路由表 printf(\"文件打开错误,按任意键退出.\\n\"); getch(); return; //start开始节点,end目的节点 GBN和路由算法实验报告 printf(\"%c->\ while (data[cur][end].from >= 0) //输出中间节点 { } total += data[cur][end].dis; printf(\"%c\\n总的路由距离 = %d\printf(\"\\n\"); total += data[cur][data[cur][end].from].dis; printf(\"%c->\cur = data[cur][end].from; for (i = 0; i < ROUTNUM; i++) { } printf(\"\\n路由表交换:\\n\"); OutputRoutData(); while(1){ printf(\"输入起始路由节点(%d-%d) : \scanf(\"%d\ &start); printf(\"输入终点路由节点(%d-%d) : \scanf(\"%d\ if (start == end || start < 0 || start > ROUTNUM-1 || end < 0 || end > { } else { int cur = start; //cur保存开始节点 int total = 0; { printf(\"没有路由路径发现!\\n\"); getch(); return; //记录总的距离 if (data[start][end].dis < 0) printf(\"\\n输入错误,请按任意键退出\\n\"); getch(); return; //打印交换的路由表 Exchange(); //更新路由表信息 }//*/ //else // printf(\"<%c -> \ printf(\"\\n\"); ROUTNUM-1) //输入错误 } /*end of if*/ GBN和路由算法实验报告 } } } printf(\"\\n\"); printf(\"\\n\"); //printf(\"\\n\"); //getch(); //return; 8. 程序运行结果部分截图 因篇幅问题不能全部显示,请点此查看更多更全内容