计算机网络实验含全部5个的代码及文字指导文档格式.docx
《计算机网络实验含全部5个的代码及文字指导文档格式.docx》由会员分享,可在线阅读,更多相关《计算机网络实验含全部5个的代码及文字指导文档格式.docx(32页珍藏版)》请在冰豆网上搜索。
(7)接收方已收到1号帧,1号窗口关闭,2号窗口打开,表示准备接收2号帧。
(8)发送方收到接收方发来的1号帧收到的确认信息,关闭1号窗口,表示从重发表中删除1号帧。
此时接收窗口状态仍不变。
若从滑动窗口的观点来统一看待1比特滑动窗口、后退N及选择重传三种协议,它们的差别仅在于各自窗口尺寸的大小不同而已:
1比特滑动窗口协议:
发送窗口=1,接收窗口=1;
后退n协议:
发窗口>
1,接收窗口>
1;
选择重传协议:
发送窗口>
1,接收窗口>
1。
1.3.2比特滑动窗口协议
当发送窗口和接收窗口的大小固定为1时,滑动窗口协议退化为停-等协议(stop-and-wait)。
该协议规定发送方每发送一帧后就要停下来,等待接收方已正确接收的确认(acknowledgement)返回后才能继续发送下一帧。
由于接收方需要判断接收到的帧是新发送的帧还是重新发送的帧,因此发送方要为每一个帧加一个序号。
由于停等协议规定只有一帧完全发送成功后才能发送新的帧,因而只用1比特来编号就够了。
1.3.3后退N协议
任何时候,若带宽与往返延迟的乘积很大,则发送方就需要一个较大的窗口。
如果带宽很高的话,即使对于一个并不很长的延迟,发送方也会很快用完它的窗口,除非窗口真的非常大。
如果延迟很长,那么即使带宽并不高,发送方也会用完它的窗口。
这两个因子的乘积基本上说明了这条管道的容量,发送方为了达到尖峰效率,需要这条管道来马不停蹄的发送数据。
这项技术称为管道化技术。
使用管道化技术后,有两种方法可以用来处理错误。
一种方法是回退n帧(实验一),另一种则是选择性重传(实验二)。
由于停等协议要为每一个帧进行确认后才继续发送下一帧,大大降低了信道利用率,因此又提出了后退N协议。
后退N协议中,发送方在发完一个数据帧后,不停下来等待应答帧,而是连续发送若干个数据帧,即使在连续发送过程中收到了接收方发来的应答帧,也可以继续发送。
而且,发送方在每发送完一个数据帧时都要设置超时定时器。
只要在所设置的超时时间内仍收到确认帧,就要重发相应的数据帧。
例如:
当发送方发送了N个帧后,若发现这N帧的前一帧在计时器超时后仍未返回其确认信息,则该帧被判定为出错或丢失,此时发送方就不得不重新发送出错的这帧及其后的N帧。
从这里不难看出,后退N协议一方面因连续发送数据帧而提高了效率,但另一方面,在重传时又必须把原来已正确传送过的数据帧进行重传(仅因这些数据帧之前有一个数据帧出了错),这种做法又使传送效率降低。
由此可见,若传输信道的传输质量很差,因而误码率较大时,连续传送协议不一定优于停止-等待协议。
此协议中的发送窗口的大小为k,接收窗口仍是1。
1.4实验步骤
1.4.1编写程序
程序源代码如下:
#include"
stdio.h"
string.h"
time.h"
conio.h"
graphics.h"
#defineN_BACKE2
#defineLENsizeof(structFrame)
intrandm(int,int);
intt;
intg_seq=1;
intg_pos=0;
structFrame
{
interr;
/*出错标志*/
intout;
/*发送标志*/
intseq;
intclock;
intack;
intcount;
/*传输次数*/
structFrame*next;
}*sd,*re;
typedefstructFrameFra;
voidInsert(Fra**,Fra*);
voidinit()/*初始化就绪、阻塞、完成队列*/
sd=NULL;
re=NULL;
}
voiddelay(inta)/*时间延迟函数,用于实现数据帧的动态变化*/
clock_tstart=clock();
/*系统时间函数*/
while(clock()-a*CLK_TCK<
=start);
voidCreat()/*创建数据帧*/
Fra*p=(Fra*)malloc(LEN);
p->
count=0;
out=0;
/*已经发送标志*/
seq=g_seq;
/*帧序号*/
clock=N_BACKE;
/*最大后退次数*/
ack=0;
/*接受确认*/
if(p->
seq%t==0)
p->
err=1;
/*出错标志*/
else
err=0;
next=NULL;
Insert(&
sd,p);
g_seq++;
voidInsert(Fra**v,Fra*p)/*将数据帧插入到V队列中*/
Fra*q;
q=*v;
if(*v==NULL)
{
q=p;
*v=q;
}
while(q->
next!
=NULL)
q=q->
next;
q->
next=p;
}
voidsend(Fra*p)/*发送数据帧*/
charstr[10];
out=1;
err==0)/*发送未出错*/
ack=1;
setfillstyle(1,4);
/*设置填充模式,用4号颜色—红表示正确发送*/
setcolor
(1);
circle(50+25*p->
seq,150,10);
/*画圆圈表示数据帧*/
floodfill(50+25*p->
seq,150,1);
setcolor
(2);
itoa(p->
seq,str,10);
outtextxy(45+25*p->
seq,146,str);
/*显示帧的编号*/
if(p->
count>
0)
{
setfillstyle(1,5);
setcolor
(1);
circle(50+25*p->
seq,300,10);
floodfill(50+25*p->
seq,300,1);
setcolor
(2);
itoa(p->
outtextxy(45+25*p->
seq,296,str);
}
else/*发送出错*/
setfillstyle(1,7);
/*用7号颜色表示错误的发送*/
setcolor(4);
outtextxy(45+25*p->
count++;
voidback_send(Fra**v)/*检查超时未确认的帧*/
intpos;
Fra*p;
p=*v;
while(p!
ack==0&
&
clock==0)/*超时未发,取得该帧标号*/
g_pos=p->
seq;
break;
}
elseif(p->
out==1)
p->
clock-=1;
p=p->
Fra*search(Fra**v,intnum)/*查找未确认帧对应的指针*/
seq==num)
returnp;
else
p=p->
intrandm(intx,inty)/*随机数函数*/
intk;
k=rand()%(x-y)+x;
returnk;
print(Fra**v)/*在屏幕上显示帧序列*/
intsize;
void*buff;
size=imagesize(65,290,85,310);
buff=malloc(size);
getimage(65,290,85,310,buff);
while(!
kbhit())
{
putimage(40+25*p->
seq,140,buff,COPY_PUT);
delay
(1);
send(p);
back_send(&
sd);
if(g_pos!
=0)
{
p=(*search)(&
sd,g_pos);
if(p->
p->
g_pos=0;
voidmain()
inti,j;
intdriver=DETECT,mode;
initgraph(&
driver,&
mode,"
"
);
cleardevice();
srand((unsigned)time(NULL));
t=randm(5,7);
for(i=0;
i<
20;
i++)
Creat();
print(&
getch();
1.4.2设计思路
本程序首先用Creat()函数创建了若干的数据帧,创建完毕后调用send(Fra*p)函数依次发送创建好的若干个数据帧,同时每发送一个帧就检查前面发送的帧是否有超时未被确认的,此功能由函数back_send(Fra**v)来完成。
若发现有超时未发则返回超时帧的序列号seq,同时根据seq调用超时帧查找函数*search(Fra**v,intnum)找到该帧位置,从该位置起全部从发后面的帧,即后退N帧协议。
1.5实验结果分析
1.5.1结果截图
1.5.2结果分析
根据后退N帧协议,当第5号帧发生错误时,第5、6、7帧全部重传(时间间隔为2个周期)。
实验二模拟实现数据链路层选择性重传协议
2.1实验目的
模拟实现数据链路层选择性重传协议。
2.2实验内容
要求编程动态实现数据链路层选择性重传协议,理解数据链路层选择性重传协议原理。
2.3实验原理
滑动窗口的基本原理同实验一。
2.3.1选择性重传协议原理
在后退N协议中,接收方若发现错误帧,就不再接收后续的帧,即便这些帧是正确到达的帧。
这显然是一种浪费。
另一种效率更高的策略是当接收方发现某帧出错后,其后继续送来的正确的帧虽然不能立即递交给接收方的高层,但接收方仍可收下来,存放在一个缓冲区中,同时要求发送方重新传送出错的那一帧。
一旦收到重新传来的帧后,就可以与已存于缓冲区中的其余帧一并按正确的顺序递交高层。
这种方法称为选择重发(SELECTIVEREPEAT),其工作过程如图所示。
显然,选择重发减少了浪费,但要求接收方有足够大的缓冲区空间。
2.4实验步骤
2.4.1编写程序
本实验的源程序和实验一基本一样,只是在某写数据的处理上有细微的差别。
即两个程序只在print(Fra**v)函数中找到超时未发数据帧的处理方面有点差别。
在实验一中,当找到超时数据帧时,直接丢弃后面的已发数据帧,即不保存后面帧的位置。
而选择性重传,由于它只重传超时的数据帧,并不重传所有的数据帧,所以当发现超时帧时,它必须先保存当前已发最后一个帧的位置,以便重发完超时帧后回到原来发送点。
voidprint(Fra**v)
Fra*p,*q;
send(p);
p=q;
/*保存当前帧位置*/
2.4.2设计思路
设计思路与实验一基本一样,不同点在上小节已详细介绍。
2.5实验结果分析
2.5.1结果截图
2.5.2结果分析
根据选择性重传协议,当6号帧发生错误时,只重传6号帧。
实验三:
距离向量路由算法的实现
3.1实验目的
模拟距离向量路由算法的路由表交换过程,演示每轮交换后路由表的变化。
3.2实验内容
要求编程实现距离矢量路由算法的路由表交换过程,并动态演示每轮交换过后路由表的变化情况。
3.3实验原理
距离向量路由算法,使用这个算法的路由器必须掌握这个距离表(它是一个一维排列,即一个向量),它告诉在网络中每个节点的最远和最近距离。
在距离表中的这个信息是根据临近接点信息的改变而时时更新的。
表中数据的量和在网络中的所有的接点(除了它自己本身)是等同的。
这个表中的列代表直接和它相连的邻居,行代表在网络中的所有目的地。
每个数据包括传送数据包到每个在网上的目的地的路径和距离/时间在那个路径上来传输(我们叫这个为“成本”)。
这个在那个算法中的度量公式是跳跃的次数,等待时间,流出数据包的数量等等。
在距离向量路由算法中,相邻路由器之间周期性地相互交换各自的路由表备份。
当网络拓扑结构发生变化时,路由器之间也将及时地相互通知有关变更信息。
每个路由器维护了一张路由表,它以子网中的每个路由器为索引,并且每个路由器对应一个表项。
该表项包含两部分:
为了达到该目标路由器而使用的输出线路,以及到达该目标路由器的时间估计值或者距离估计值。
距离矢量路由算法在理论中可以工作,但在实践中有一个严重的缺陷:
虽然它总是能够达到正确的答案,但是它收敛到正确答案的速度非常慢,尤其是,它对于好消息的反应非常快,但是对于坏消息的反应非常迟缓。
3.4实验步骤
3.4.1编写程序
程序的源代码如下:
stdlib.h"
alloc.h"
#defineROUTNUM7
typedefstruct
intdis;
intfrom;
}RoutNode;
RoutNodedata[ROUTNUM][ROUTNUM];
/*路由表*/
voidInitData(FILE*pfile);
/*从数据文件读取数据,初始化路由表*/
voidOutputRoutData();
/*输出所有的路由表*/
voidCommunication(intrecv,intsend);
/*send点向recv点发送自己的路由表*/
voidExchange();
/*所有节点进行一次数据交换,更新路由表*/
intstart,end,i,j;
FILE*pfile;
pfile=fopen("
1.txt"
"
r"
if(pfile==NULL)
printf("
文件打开错误,按任意键退出.\n"
getch();
return;
InitData(pfile);
fclose(pfile);
printf("
\n路由表初始:
\n"
i<
ROUTNUM;
%c||"
i+65);
for(j=0;
j<
ROUTNUM;
j++)
if(data[i][j].dis>
printf("
<
%c%d>
"
j+65,data[i][j].dis);
Exchange();
\n路由表交换:
OutputRoutData();
输入起始路由节点(%d-%d):
0,ROUTNUM-1);
scanf("
%d"
&
start);
输入终点路由节点(%d-%d):
end);
if(start==end||start<
0||start>
6||end<
0||end>
6)
\n输入错误,请按任意键退出\n"
intcur=start;
inttotal=0;
if(data[start][end].dis<
printf("
没有路由路径发现!
getch();
return;
}/*endofif*/
%c->
cur+65);
while(data[cur][end].from>
total+=data[cur][data[cur][end].from].dis;
data[cur][end].from+65);
cur=data[cur][end].from;
}/*endofwhile*/
total+=data[cur][end].dis;
%c\n总的路由距离=%d"
end+65,total);
}/*endofelse*/
voidInitData(FILE*pfile)
charnum[10];
inti=0;
charc;
intm,n;