云南大学软件学院计算机网络原理实验六实验报告.docx
《云南大学软件学院计算机网络原理实验六实验报告.docx》由会员分享,可在线阅读,更多相关《云南大学软件学院计算机网络原理实验六实验报告.docx(39页珍藏版)》请在冰豆网上搜索。
云南大学软件学院计算机网络原理实验六实验报告
实验六、传输层可靠传输协议GBN编程实验报告
序号:
姓名:
学号:
成绩指导老师:
一、实验目的:
1、通过编写实现一个简单可靠的数据传输协议GBN的发送和接收代码,模拟可靠数据传输
2、理解TCP协议可靠传输的差错检测、重传、累计确认、定时器的可靠传输策略。
二、实验指导:
参考教材。
动画演示:
三、实验要求:
编程实现一个GBN传输协议的发送方和接收方两程序,采用编程语言不限,要求能将发送――接收流程以及处理方法表现出来.
1.实验流程图如下:
选择重传
Y
N
2.实验截图与代码如下:
截图:
代码及注释:
一、GBN.h
#pragmaonce
#include
//基础功能模块的数据结构声明
#defineBIDIRECTIONAL1/*changeto1ifyou'redoingextracreditandwritearoutinecalledB_output*/
/*a"msg"isthedataunitpassedfromlayer5(teacherscode)tolayer4(students'code).Itcontainsthedata(characters)tobedeliveredtolayer5viathestudentstransportlevelprotocolentities.*/
structmsg
{chardata[20];
};
/*apacketisthedataunitpassedfromlayer4(studentscode)tolayer3(teacherscode).Notethepre-definedpacketstructure,whichall
studentsmustfollow.*/
structpkt
{
intseqnum;
intacknum;
intchecksum;
charpayload[20];
};
#defineWINDOWSIZE8
#defineMAXBUFSIZE50
#defineRTT15.0
#defineNOTUSED0
#defineNACK-1
#defineTRUE1
#defineFALSE0
#defineA0
#defineB1
//网络仿真部分数据结构声明***********************************************************
structevent
{
floatevtime;/*eventtime*/
intevtype;/*eventtypecode*/
inteventity;/*entitywhereeventoccurs*/
structpkt*pktptr;/*ptrtopacket(ifany)assocw/thisevent*/
structevent*prev;
structevent*next;
};
/*possibleevents:
*/
#defineTIMER_INTERRUPT0
#defineFROM_LAYER51
#defineFROM_LAYER32
#defineOFF0
#defineON1
//基础功能模块的函数声明*******************************************************************
voidComputeChecksum(structpkt*packet);//计算校验和
intCheckCorrupted(structpktpacket);//检查数据是否出错
voidA_output(structmsgmessage);//A端向外发送数据
voidA_input(structpktpacket);//A端接收数据
voidA_timerinterrupt();//A计时器超时
voidA_init();//A端初始化
voidB_output(structmsgmessage);
voidB_input(structpktpacket);
voidB_timerinterrupt();
voidB_init();
//网络仿真部分的函数声明**************************************************
voidinit();//初始化仿真器
floatjimsrand();//随机数发生器[0,1]
//处理事件列表部分的函数声明*********************************************
voidgenerate_next_arrival();//产生下一个到达的分组
voidinsertevent(structevent*p);//向事件列表中插入一条新的事件
voidprintevlist();//打印事件列表
//********************************************************************
//**********************计时器模块***********************************
voidstoptimer(int);//停止计时器
voidstarttimer(int,float);//启动计时器
//*********************************************************************
//**************************网络各层之间传送模块***********************
voidtolayer3(intAorB,structpktpacket);//向第3层发送信息
voidtolayer5(intAorB,chardatasent[20]);//向第5层发送信息
二、GBN.c
#include"GBN.h"
#include
#include
#include
externintTRACE=1;/*formydebugging*/为我的调试
externintnsim=0;/*numberofmessagesfrom5to4sofar*/目前为止信息的数字是从5到4
externintnsimmax=0;/*numberofmsgstogenerate,thenstop*/如果信息产生的数字为0,然后就停止
externfloattime=0.000;
floatlossprob;/*probabilitythatapacketisdropped*/数据包可能会丢失
floatcorruptprob;/*probabilitythatonebitispacketisflipped*/这一点的数据包可能会被弹出去
floatlambda;/*arrivalrateofmessagesfromlayer5*/第五层到达的信息的次序
intntolayer3;/*numbersentintolayer3*/被传送到第三层的数据
staticintnlost=0;/*numberlostinmedia*/在媒介中数据丢失
static int ncorrupt = 0; /* number corrupted by media*/ 被媒介毁坏的数据
static int expectedseqnum = 0; /* expected sequence number at receiver side */ 在接收者这边接收到预期的序列数据
static int nextseqnum; /* next sequence number to use in sender side */ 下一个序列数据使用在发送者这边 static int base; /* the head of sender window */ 发送者的头窗口
struct pkt winbuf[WINDOWSIZE]; /* window packets buffer */ 数据包缓冲区窗口
static int winfront,winrear; /* front and rear points of window buffer */ 窗口缓冲区的前方点和后方点
static int pktnum; /* packet number of window buffer */ 窗口缓冲区的数据包个数
struct msg buffer[MAXBUFSIZE]; /* sender message buffer */ 发送消息缓冲区
int buffront,bufrear; /* front and rear pointers of buffer */ 缓冲区的前指针与后指针
static int msgnum; /* message number of buffer */
信息数量的缓冲
intpacket_lost=0;
intpacket_corrupt=0;
intpacket_sent=0;
externintpacket_correct=0;
externintpacket_resent=0;
intpacket_timeout=0;
externstructevent*evlist=NULL;/*theeventlist*/
//计算校验和
voidComputeChecksum(structpkt*packet)
{
intchecksum;
inti;
checksum=packet->seqnum;
checksum=checksum+packet->acknum;
for(i=0;i<20;i++)
checksum=checksum+(int)(packet->payload[i]);
checksum=0-checksum;
packet->checksum=checksum;
}
//检查是否出错
intCheckCorrupted(structpktpacket)
{
intchecksum;
inti;
checksum=packet.seqnum;
checksum=checksum+packet.acknum;
for(i=0;i<20;i++)
checksum=checksum+(int)(packet.payload[i]);
if((packet.checksum+checksum)==0)
return(FALSE);
else
return(TRUE);
}
//A端向外发送数据
/*calledfromlayer5,passedthedatatobesenttootherside*/
voidA_output(structmsgmessage)
{
inti;
structpktsendpkt;
/*ifwindowisnotfull*/
if(nextseqnum
{
printf("----A:
Newmessagearrives,sendwindowisnotfull,sendnewmessgetolayer3!
\n");
/*createpacket*/
sendpkt.seqnum=nextseqnum;
sendpkt.acknum=NOTUSED;
for(i=0;i<20;i++)
sendpkt.payload[i]=message.data[i];
/*computerchecksum*/
ComputeChecksum(&sendpkt);
/*sendoutpacket*/
tolayer3(A,sendpkt);
/*copythepackettowindowpacketbuffer*/
winrear=(winrear+1)%WINDOWSIZE;
pktnum++;
winbuf[winrear]=sendpkt;
for(i=0;i<20;i++)
winbuf[winrear].payload[i]=sendpkt.payload[i];
/*updatestatevariables*/
nextseqnum=nextseqnum+1;
starttimer(A,RTT);
B_input(sendpkt);
A_input(sendpkt);
}
/*ifwindowisfull*/
else
{
printf("----A:
Newmessagearrives,sendwindowisfull,");
/*ifbufferfull,giveupandexit*/
if(msgnum==MAXBUFSIZE)
{
printf("Error:
Senderbufferisfull!
\n");
exit
(1);
}
/*otherwise,bufferthemessage*/
else
{
printf("buffernewmessage!
\n");
bufrear=(bufrear+1)%MAXBUFSIZE;
for(i=0;i<20;i++)
buffer[bufrear].data[i]=message.data[i];
msgnum++;
}
}
}
//B端向外发送数据
/*calledfromlayer5,passedthedatatobesenttootherside*/
voidB_output(structmsgmessage)
{
inti;
structpktsendpkt;
/*ifwindowisnotfull*/
if(nextseqnum
{
printf("----A:
Newmessagearrives,sendwindowisnotfull,sendnewmessgetolayer3!
\n");
/*createpacket*/
sendpkt.seqnum=nextseqnum;
sendpkt.acknum=NOTUSED;
for(i=0;i<20;i++)
sendpkt.payload[i]=message.data[i];
/*computerchecksum*/
ComputeChecksum(&sendpkt);
/*sendoutpacket*/
tolayer3(A,sendpkt);
A_input(sendpkt);
/*copythepackettowindowpacketbuffer*/
winrear=(winrear+1)%WINDOWSIZE;
pktnum++;
winbuf[winrear]=sendpkt;
for(i=0;i<20;i++)
winbuf[winrear].payload[i]=sendpkt.payload[i];
/*ifitisthefirstpacketinwindow,starttimeout*/
//if(base==nextseqnum)
//{
//starttimer(A,RTT);
//printf("----A:
startanewtimer!
\n");
//}
/*updatestatevariables*/
nextseqnum=nextseqnum+1;
}
/*ifwindowisfull*/
else
{
printf("----A:
Newmessagearrives,sendwindowisfull,");
/*ifbufferfull,giveupandexit*/
if(msgnum==MAXBUFSIZE)
{
printf("Error:
Senderbufferisfull!
\n");
exit
(1);
}
/*otherwise,bufferthemessage*/
else
{
printf("buffernewmessage!
\n");
bufrear=(bufrear+1)%MAXBUFSIZE;
for(i=0;i<20;i++)
buffer[bufrear].data[i]=message.data[i];
msgnum++;
}
}
}
//A端接收数据
voidA_input(structpktpacket)
{
structpktsendpkt;
inti;
/*ifreceivedpacketisnotcorruptedandACKisreceived*/
if((CheckCorrupted(packet)==FALSE)&&(packet.acknum!
=NACK))
{
printf("----A:
ACK%discorrectlyreceived,",packet.acknum);
packet_correct++;
/*deletetheackedpacketsfromwindowbuffer*/
winfront=(winfront+(packet.acknum+1-base))%WINDOWSIZE;
pktnum=pktnum-(packet.acknum+1-base);
/*movewindowbase*/
base=packet.acknum+1;
stoptimer(A);
if(base{
//starttimer(A,RTT);
printf("\n\n\nsendnewpackets!
");
}
/*ifbufferisnotempty,sendnewpackets*/
while((msgnum!
=0)&&(nextseqnum
{
/*createpacket*/
sendpkt.seqnum=nextseqnum;
sendpkt.acknum=NOTUSED;
buffront=(buffront+1)%MAXBUFSIZE;
for(i=0;i<20;i++)
sendpkt.payload[i]=buffer[buffront].data[i];
/*computerchecksum*/
ComputeChecksum(&sendpkt);
/*ifitisthefirstpacketinwindow,starttimeout*/
if(base==nextseqnum)
{
//starttimer(A,RTT);
printf("sendnewpackets!
\n");
}
/*sendoutpacket*/
tolayer3(A,sendpkt);
/*copythepackettowindowpacketbuffer*/
winrear=(winrear+1)%WINDOWSIZE;
winbuf[winrear]=sendpkt;
pktnum++;
/*updatestatevariables*/
nextseqnum=nextseqnum+1;
/*deletemessa