云南大学软件学院计算机网络基础原理实验六实验报告.doc
实验六、传输层可靠传输协议GBN编程实验报告序号: 姓名: 学号: 成绩 指导老师: 一、实验目的:1、通过编写实现一个简单可靠的数据传输协议GBN的发送和接收代码,模拟可靠数据传输2、理解TCP协议可靠传输的差错检测、重传、累计确认、定时器的可靠传输策略。二、实验指导:参考教材。动画演示:http:/resource.jingpinke.com/details?uuid=ff808081-284d0365-0128-4d0450cc-1e4b&objectId=oid:ff808081-284d0365-0128-4d0450cc-1e4c三、实验要求:编程实现一个GBN传输协议的发送方和接收方两程序,采用编程语言不限,要求能将发送接收流程以及处理方法表现出来.开始1.实验流程图如下:变量初始化, 结构体等的定义计时器,时间表等处理函数的声明与实现A端和B端的初始化,A端和B端的发出函数以及接收函数的定义及声明,随机数生成器。A端创建发送数据包,计算机校验,B端接收数据包。判断数据包超时,丢包,损坏选择重传选择重传Y判断是否传送完毕 N 传送下一个数据包结束2.实验截图与代码如下:截图:代码及注释:一、 GBN.h#pragma once#include /基础功能模块的数据结构声明#define BIDIRECTIONAL 1 /* change to 1 if youre doing extra credit and write a routine called B_output */* a msg is the data unit passed from layer 5 (teachers code) to layer 4 (students code). It contains the data (characters) to be delivered to layer 5 via the students transport level protocol entities. */struct msg char data20;/* a packet is the data unit passed from layer 4 (students code) to layer 3 (teachers code). Note the pre-defined packet structure, which all students must follow. */struct pktint seqnum;int acknum;int checksum;char payload20;#define WINDOWSIZE 8#define MAXBUFSIZE 50#define RTT 15.0#define NOTUSED 0#define NACK -1#define TRUE 1#define FALSE 0#define A 0#define B 1/网络仿真部分数据结构声明*struct eventfloat evtime; /* event time */int evtype; /* event type code */int eventity; /* entity where event occurs */struct pkt *pktptr; /* ptr to packet (if any) assoc w/ this event */struct event *prev;struct event *next; ;/* possible events: */#define TIMER_INTERRUPT 0 #define FROM_LAYER5 1#define FROM_LAYER3 2#define OFF 0#define ON 1/基础功能模块的函数声明*void ComputeChecksum(struct pkt *packet);/计算校验和int CheckCorrupted(struct pkt packet);/检查数据是否出错void A_output( struct msg message);/A端向外发送数据void A_input(struct pkt packet);/A端接收数据void A_timerinterrupt();/A计时器超时void A_init();/A端初始化void B_output(struct msg message); void B_input(struct pkt packet);void B_timerinterrupt();void B_init();/网络仿真部分的函数声明*void init(); /初始化仿真器float jimsrand();/随机数发生器0,1/处理事件列表部分的函数声明*void generate_next_arrival();/产生下一个到达的分组void insertevent(struct event *p);/向事件列表中插入一条新的事件void printevlist();/打印事件列表/*/*计时器模块*void stoptimer(int);/停止计时器void starttimer(int,float);/启动计时器/*/*网络各层之间传送模块*void tolayer3(int AorB,struct pkt packet);/向第3层发送信息void tolayer5(int AorB,char datasent20);/向第5层发送信息二、 GBN.c#include GBN.h#include #include #include extern int TRACE = 1; /* for my debugging */为我的调试extern int nsim = 0; /* number of messages from 5 to 4 so far */目前为止信息的数字是从5到4extern int nsimmax = 0; /* number of msgs to generate, then stop */如果信息产生的数字为0,然后就停止extern float time = 0.000;float lossprob; /* probability that a packet is dropped */数据包可能会丢失float corruptprob; /* probability that one bit is packet is flipped */这一点的数据包可能会被弹出去float lambda; /* arrival rate of messages from layer 5 */ 第五层到达的信息的次序int ntolayer3; /* number sent into layer 3 */被传送到第三层的数据static int nlost = 0; /* number lost in media */在媒介中数据丢失staticintncorrupt=0;/*numbercorruptedbymedia*/被媒介毁坏的数据staticintexpectedseqnum=0;/*expectedsequencenumberatreceiverside*/在接收者这边接收到预期的序列数据staticintnextseqnum;/*nextsequencenumbertouseinsenderside*/下一个序列数据使用在发送者这边staticintbase;/*theheadofsenderwindow*/发送者的头窗口structpktwinbufWINDOWSIZE;/*windowpacketsbuffer*/数据包缓冲区窗口staticintwinfront,winrear;/*frontandrearpointsofwindowbuffer*/窗口缓冲区的前方点和后方点staticintpktnum;/*packetnumberofwindowbuffer*/窗口缓冲区的数据包个数structmsgbufferMAXBUFSIZE;/*sendermessagebuffer*/发送消息缓冲区intbuffront,bufrear;/*frontandrearpointersofbuffer*/缓冲区的前指针与后指针staticintmsgnum;/*messagenumberofbuffer*/信息数量的缓冲int packet_lost =0; int packet_corrupt=0;int packet_sent =0;extern int packet_correct=0;extern int packet_resent =0;int packet_timeout=0;extern struct event *evlist = NULL; /* the event list */计算校验和void ComputeChecksum( struct pkt *packet) int checksum;int i;checksum = packet-seqnum;checksum = checksum + packet-acknum;for ( i=0; ipayloadi);checksum = 0-checksum;packet-checksum = checksum;/检查是否出错int CheckCorrupted(struct pkt packet)int checksum;int i;checksum = packet.seqnum;checksum = checksum + packet.acknum;for ( i=0; i20; i+ ) checksum = checksum + (int)(packet.payloadi);if ( (packet.checksum+checksum) = 0 )return (FALSE);elsereturn (TRUE);/A端向外发送数据/* called from layer 5, passed the data to be sent to other side */void A_output(struct msg message)int i;struct pkt sendpkt;/* if window is not full */if ( nextseqnum base+WINDOWSIZE )printf(-A: New message arrives, send window is not full, send new messge to layer3!n);/* create packet */sendpkt.seqnum = nextseqnum;sendpkt.acknum = NOTUSED;for ( i=0; i20 ; i+ ) sendpkt.payloadi = message.datai;/* computer checksum */ComputeChecksum (&sendpkt); /* send out packet */ tolayer3 (A, sendpkt); /* copy the packet to window packet buffer */ winrear = (winrear+1)%WINDOWSIZE; pktnum +; winbufwinrear = sendpkt; for (i=0; i20; i+) winbufwinrear.payloadi= sendpkt.payloadi; /* update state variables */ nextseqnum = nextseqnum+1; starttimer(A,RTT); B_input(sendpkt); A_input(sendpkt);/* if window is full */else printf(-A: New message arrives, send window is full,);/* if buffer full, give up and exit*/if ( msgnum = MAXBUFSIZE)printf ( Error: Sender buffer is full! n); exit (1); /* otherwise, buffer the message */ else printf(buffer new message!n); bufrear = (bufrear+1) % MAXBUFSIZE; for (i=0; i20; i+) bufferbufrear.datai = message.datai; msgnum +; /B端向外发送数据/* called from layer 5, passed the data to be sent to other side */void B_output(struct msg message)int i;struct pkt sendpkt;/* if window is not full */if ( nextseqnum base+WINDOWSIZE )printf(-A: New message arrives, send window is not full, send new messge to layer3!n);/* create packet */sendpkt.seqnum = nextseqnum;sendpkt.acknum = NOTUSED;for ( i=0; i20 ; i+ ) sendpkt.payloadi = message.datai;/* computer checksum */ComputeChecksum (&sendpkt); /* send out packet */ tolayer3 (A, sendpkt);A_input(sendpkt); /* copy the packet to window packet buffer */ winrear = (winrear+1)%WINDOWSIZE; pktnum +; winbufwinrear = sendpkt; for (i=0; i20; i+) winbufwinrear.payloadi= sendpkt.payloadi; /* if it is the first packet in window, start timeout */ /if ( base = nextseqnum ) / /starttimer(A,RTT); /printf(-A: start a new timer!n); / /* update state variables */ nextseqnum = nextseqnum+1;/* if window is full */else printf(-A: New message arrives, send window is full,);/* if buffer full, give up and exit*/if ( msgnum = MAXBUFSIZE)printf ( Error: Sender buffer is full! n); exit (1); /* otherwise, buffer the message */ else printf(buffer new message!n); bufrear = (bufrear+1) % MAXBUFSIZE; for (i=0; i20; i+) bufferbufrear.datai = message.datai; msgnum +; /A端接收数据void A_input(struct pkt packet)struct pkt sendpkt;int i;/* if received packet is not corrupted and ACK is received */ if ( (CheckCorrupted(packet) = FALSE) & (packet.acknum != NACK) )printf(-A: ACK %d is correctly received,packet.acknum);packet_correct+; /* delete the acked packets from window buffer */ winfront = (winfront+(packet.acknum+1-base) % WINDOWSIZE; pktnum = pktnum - (packet.acknum+1-base); /* move window base */ base = packet.acknum+1; stoptimer(A); if ( base nextseqnum) /starttimer(A,RTT); printf (nnnsend new packets!); /* if buffer is not empty, send new packets */ while ( (msgnum!=0) & (nextseqnumbase+WINDOWSIZE) )/* create packet */ sendpkt.seqnum = nextseqnum; sendpkt.acknum = NOTUSED; buffront = (buffront+1) % MAXBUFSIZE; for ( i=0; i20 ; i+ ) sendpkt.payloadi = bufferbuffront.datai; /* computer checksum */ ComputeChecksum (&sendpkt); /* if it is the first packet in window, start timeout */ if ( base = nextseqnum )/starttimer(A,RTT);printf (send new packets!n); /* send out packet */ tolayer3 (A, sendpkt); /* copy the packet to window packet buffer */ winrear = (winrear+1)%WINDOWSIZE; winbufwinrear = sendpkt; pktnum +; /* update state variables */nextseqnum = nextseqnum+1; /* delete message from buffer */msgnum -;else printf (-A: NACK is received, do nothing!n);/B端接收数据*一定要调用这个/* Note that with simplex transfer from a-to-B, there is no B_output() */* called from layer 3, when a packet arrives for layer 4 at B*/void B_input(struct pkt packet) struct pkt sendpkt;int i;/* if not corrupted and received packet is in order */if ( (CheckCorrupted(packet) = FALSE) & (packet.seqnum = expectedseqnum)printf(n-B: packet %d is correctly received, send ACK!n,packet.seqnum);/* send an ACK for the received packet */ /* create packet */ sendpkt.seqnum = NOTUSED; sendpkt.acknum = expectedseqnum; for ( i=0; i20 ; i+ )sendpkt.payloadi = 0; /* computer checksum */ ComputeChecksum (&sendpkt); /* send out packet */tolayer3 (B, sendpkt);/* update state variables */expectedseqnum = expectedseqnum+1; printf(-B:expectedseqnum = %dn,expectedseqnum); /* deliver received packet to layer 5 */ /tolayer5(B,packet.payload); /* otherwise, discard the packet and send a NACK */ elseprintf(-B: packet %d is corrupted or not I expects, send NACK!n,packet.seqnum); /* create packet */ sendpkt.seqnum = NOTUSED; sendpkt.acknum = NACK; for ( i=0; i20 ; i+ ) sendpkt.payloadi = 0; /* computer checksum */ ComputeChecksum (&sendpkt); /* send out packet */ tolayer3 (B, sendpkt); /A计时器超时/* called when As timer goes off */void A_timerinterrupt()int i;printf(-A: time out,resend packets!n);/* start timer */starttimer(A,RTT);/* resend all packets not acked */for ( i=1; i=pktnum; i+ )packet_resent+; tolayer3(A,winbuf(winfront+i)%WINDOWSIZE); /B计时器超时/* called when Bs timer goes off */void B_timerinterrupt()int i;printf(-B: time out,resend packets!n);/* start timer */starttimer(B,RTT);/* resend all packets not acked */for ( i=1; i 0.0: ); /fscanf(fp,%f,&lambda);scanf(%f,&lambda); printf(nEnter TRACE: );/fscanf(fp,%d,&TRACE);scanf(%d,&TRACE);printf(nn);srand(9999); /* init random number generator */sum = 0.0; /* test random number generator for students */for (i=0; i1000; i+)sum=sum+jimsrand(); /* jimsrand() should be uniform in 0,1 */avg = sum/1000.0; /*if(avg 0.75)
收藏
- 资源描述:
-
^`
实验六、传输层可靠传输协议GBN编程实验报告
序号: 姓名: 学号: 成绩 指导老师:
一、实验目的:
1、通过编写实现一个简单可靠的数据传输协议GBN的发送和接收代码,模拟可靠数据传输
2、理解TCP协议可靠传输的差错检测、重传、累计确认、定时器的可靠传输策略。
二、实验指导:
参考教材。
动画演示:
http://resource.jingpinke.com/details?uuid=ff808081-284d0365-0128-4d0450cc-1e4b&objectId=oid:ff808081-284d0365-0128-4d0450cc-1e4c
三、实验要求:
编程实现一个GBN传输协议的发送方和接收方两程序,采用编程语言不限,要求能将发送――接收流程以及处理方法表现出来.
开始
1.实验流程图如下:
变量初始化, 结构体等的定义
计时器,时间表等处理函数的声明与实现
A端和B端的初始化,A端和B端的发出函数以及接收函数的定义及声明,随机数生成器。
A端创建发送数据包,计算机校验,B端接收数据包。
判断数据包超
时,丢包,损坏
选择重传
选择重传
Y 判断是否传送完毕
N
传送下一个数据包
结束
2.实验截图与代码如下:
截图:
代码及注释:
一、 GBN.h
#pragma once
#include
//基础功能模块的数据结构声明
#define BIDIRECTIONAL 1 /* change to 1 if youre doing extra credit and write a routine called B_output */
/* a "msg" is the data unit passed from layer 5 (teachers code) to layer 4 (students code). It contains the data (characters) to be delivered to layer 5 via the students transport level protocol entities. */
struct msg
{ char data[20];
};
/* a packet is the data unit passed from layer 4 (students code) to layer 3 (teachers code). Note the pre-defined packet structure, which all
students must follow. */
struct pkt
{
int seqnum;
int acknum;
int checksum;
char payload[20];
};
#define WINDOWSIZE 8
#define MAXBUFSIZE 50
#define RTT 15.0
#define NOTUSED 0
#define NACK -1
#define TRUE 1
#define FALSE 0
#define A 0
#define B 1
//网络仿真部分数据结构声明***********************************************************
struct event
{
float evtime; /* event time */
int evtype; /* event type code */
int eventity; /* entity where event occurs */
struct pkt *pktptr; /* ptr to packet (if any) assoc w/ this event */
struct event *prev;
struct event *next;
};
/* possible events: */
#define TIMER_INTERRUPT 0
#define FROM_LAYER5 1
#define FROM_LAYER3 2
#define OFF 0
#define ON 1
//基础功能模块的函数声明*******************************************************************
void ComputeChecksum(struct pkt *packet);//计算校验和
int CheckCorrupted(struct pkt packet);//检查数据是否出错
void A_output( struct msg message);//A端向外发送数据
void A_input(struct pkt packet);//A端接收数据
void A_timerinterrupt();//A计时器超时
void A_init();//A端初始化
void B_output(struct msg message);
void B_input(struct pkt packet);
void B_timerinterrupt();
void B_init();
//网络仿真部分的函数声明**************************************************
void init(); //初始化仿真器
float jimsrand();//随机数发生器[0,1]
//处理事件列表部分的函数声明*********************************************
void generate_next_arrival();//产生下一个到达的分组
void insertevent(struct event *p);//向事件列表中插入一条新的事件
void printevlist();//打印事件列表
//********************************************************************
//**********************计时器模块***********************************
void stoptimer(int);//停止计时器
void starttimer(int,float);//启动计时器
//*********************************************************************
//**************************网络各层之间传送模块***********************
void tolayer3(int AorB,struct pkt packet);//向第3层发送信息
void tolayer5(int AorB,char datasent[20]);//向第5层发送信息
二、 GBN.c
#include "GBN.h"
#include
#include
#include
extern int TRACE = 1; /* for my debugging */为我的调试
extern int nsim = 0; /* number of messages from 5 to 4 so far */目前为止信息的数字是从5到4
extern int nsimmax = 0; /* number of msgs to generate, then stop */如果信息产生的数字为0,然后就停止
extern float time = 0.000;
float lossprob; /* probability that a packet is dropped */数据包可能会丢失
float corruptprob; /* probability that one bit is packet is flipped */这一点的数据包可能会被弹出去
float lambda; /* arrival rate of messages from layer 5 */ 第五层到达的信息的次序
int ntolayer3; /* number sent into layer 3 */被传送到第三层的数据
static int nlost = 0; /* number lost in media */在媒介中数据丢失
staticintncorrupt=0;/*numbercorruptedbymedia*/被媒介毁坏的数据
staticintexpectedseqnum=0;/*expectedsequencenumberatreceiverside*/在接收者这边接收到预期的序列数据
staticintnextseqnum;/*nextsequencenumbertouseinsenderside*/下一个序列数据使用在发送者这边staticintbase;/*theheadofsenderwindow*/发送者的头窗口
structpktwinbuf[WINDOWSIZE];/*windowpacketsbuffer*/数据包缓冲区窗口
staticintwinfront,winrear;/*frontandrearpointsofwindowbuffer*/窗口缓冲区的前方点和后方点
staticintpktnum;/*packetnumberofwindowbuffer*/窗口缓冲区的数据包个数
structmsgbuffer[MAXBUFSIZE];/*sendermessagebuffer*/发送消息缓冲区
intbuffront,bufrear;/*frontandrearpointersofbuffer*/缓冲区的前指针与后指针
staticintmsgnum;/*messagenumberofbuffer*/
信息数量的缓冲
int packet_lost =0;
int packet_corrupt=0;
int packet_sent =0;
extern int packet_correct=0;
extern int packet_resent =0;
int packet_timeout=0;
extern struct event *evlist = NULL; /* the event list */
//计算校验和
void ComputeChecksum( struct pkt *packet)
{
int checksum;
int i;
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;
}
//检查是否出错
int CheckCorrupted(struct pkt packet)
{
int checksum;
int i;
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端向外发送数据
/* called from layer 5, passed the data to be sent to other side */
void A_output(struct msg message)
{
int i;
struct pkt sendpkt;
/* if window is not full */
if ( nextseqnum < base+WINDOWSIZE )
{
printf("----A: New message arrives, send window is not full, send new messge to layer3!\n");
/* create packet */
sendpkt.seqnum = nextseqnum;
sendpkt.acknum = NOTUSED;
for ( i=0; i<20 ; i++ )
sendpkt.payload[i] = message.data[i];
/* computer checksum */
ComputeChecksum (&sendpkt);
/* send out packet */
tolayer3 (A, sendpkt);
/* copy the packet to window packet buffer */
winrear = (winrear+1)%WINDOWSIZE;
pktnum ++;
winbuf[winrear] = sendpkt;
for (i=0; i<20; i++)
winbuf[winrear].payload[i]= sendpkt.payload[i];
/* update state variables */
nextseqnum = nextseqnum+1;
starttimer(A,RTT);
B_input(sendpkt);
A_input(sendpkt);
}
/* if window is full */
else
{
printf("----A: New message arrives, send window is full,");
/* if buffer full, give up and exit*/
if ( msgnum == MAXBUFSIZE)
{
printf (" Error: Sender buffer is full! \n");
exit (1);
}
/* otherwise, buffer the message */
else
{
printf("buffer new message!\n");
bufrear = (bufrear+1) % MAXBUFSIZE;
for (i=0; i<20; i++)
buffer[bufrear].data[i] = message.data[i];
msgnum ++;
}
}
}
//B端向外发送数据
/* called from layer 5, passed the data to be sent to other side */
void B_output(struct msg message)
{
int i;
struct pkt sendpkt;
/* if window is not full */
if ( nextseqnum < base+WINDOWSIZE )
{
printf("----A: New message arrives, send window is not full, send new messge to layer3!\n");
/* create packet */
sendpkt.seqnum = nextseqnum;
sendpkt.acknum = NOTUSED;
for ( i=0; i<20 ; i++ )
sendpkt.payload[i] = message.data[i];
/* computer checksum */
ComputeChecksum (&sendpkt);
/* send out packet */
tolayer3 (A, sendpkt);
A_input(sendpkt);
/* copy the packet to window packet buffer */
winrear = (winrear+1)%WINDOWSIZE;
pktnum ++;
winbuf[winrear] = sendpkt;
for (i=0; i<20; i++)
winbuf[winrear].payload[i]= sendpkt.payload[i];
/* if it is the first packet in window, start timeout */
//if ( base == nextseqnum )
//{
//starttimer(A,RTT);
//printf("----A: start a new timer!\n");
// }
/* update state variables */
nextseqnum = nextseqnum+1;
}
/* if window is full */
else
{
printf("----A: New message arrives, send window is full,");
/* if buffer full, give up and exit*/
if ( msgnum == MAXBUFSIZE)
{
printf (" Error: Sender buffer is full! \n");
exit (1);
}
/* otherwise, buffer the message */
else
{
printf("buffer new message!\n");
bufrear = (bufrear+1) % MAXBUFSIZE;
for (i=0; i<20; i++)
buffer[bufrear].data[i] = message.data[i];
msgnum ++;
}
}
}
//A端接收数据
void A_input(struct pkt packet)
{
struct pkt sendpkt;
int i;
/* if received packet is not corrupted and ACK is received */
if ( (CheckCorrupted(packet) == FALSE) && (packet.acknum != NACK) )
{
printf("----A: ACK %d is correctly received,",packet.acknum);
packet_correct++;
/* delete the acked packets from window buffer */
winfront = (winfront+(packet.acknum+1-base)) % WINDOWSIZE;
pktnum = pktnum - (packet.acknum+1-base);
/* move window base */
base = packet.acknum+1;
stoptimer(A);
if ( base < nextseqnum)
{
//starttimer(A,RTT);
printf ("\n\n\nsend new packets!");
}
/* if buffer is not empty, send new packets */
while ( (msgnum!=0) && (nextseqnum 0.0]: ");
//fscanf(fp,"%f",&lambda);
scanf("%f",&lambda);
printf("\nEnter TRACE: ");
//fscanf(fp,"%d",&TRACE);
scanf("%d",&TRACE);
printf("\n\n");
srand(9999); /* init random number generator */
sum = 0.0; /* test random number generator for students */
for (i=0; i<1000; i++)
sum=sum+jimsrand(); /* jimsrand() should be uniform in [0,1] */
avg = sum/1000.0;
/*if(avg < 0.25 || avg > 0.75)
{
展开阅读全文