返回NARQ 协议.docx
《返回NARQ 协议.docx》由会员分享,可在线阅读,更多相关《返回NARQ 协议.docx(17页珍藏版)》请在冰豆网上搜索。
返回NARQ协议
实验报告
题目:
返回N-ARQ协议
实验内容:
实现收接双方的返回N-ARQ协议。
实验要求:
进行实时的传输控制以及现实差错模拟
实验基本思想:
将发送方A的源文件(假设为1.txt)经过有序的切分之后送入缓冲双向队列之中,按照事先规定好的速率进行实时传输。
接收方B接收到相应的分组之后进行回应,然后A根据回应对确认分组进行销毁,调整分发帧继续重传
实验结构:
checksum.h
12
34
receiver_function.h
ARQ-body
send_functiom.h
56
代码:
opinion.h
timer.h
table.h
界面
789
10
1.发送帧校验和检查
2.接收分组校验和检查
3.反馈接收
4.反馈传输
5.帧传输
6.帧接收
7.基本参数设定
8.当前链路状态参数传输
9.随机计时器
10.链路状态窗口调用
代码:
ARQ-body:
#include
#include
#include
#include
#include
#include
#include
usingnamespacestd;
#include"check_sum.h"
#include"opinion.h"
#include"table.h"
#include"send_function.h"
#include"timer.h"
#include"receive_function.h"
intmain(intargc,char*argv[])///////////////////////////////////用来初始化双方数据:
默认双方使用缓冲区大小为5:
3
{
chars1[30]={'1','.','t','x','t'};
chars2[30]={'2','.','t','x','t'};
inti;
if(argc!
=1)
{
strcpy(s1,argv[0]);
strcpy(s2,argv[1]);
}
fin.open(s1);
if(!
fin.good())
return1;
fout.open(s2);
if(!
fout.good())
return1;
while(true)
{
if(!
GetData())//////////////////////将当前文件的一个块插进队列1
break;
SendFrame();////////////////////文件发送
receive();
}
fin.close();
fout.close();
return1;
}
check_sum.h
intcheck_sum(char*puchMsg)
{
///////////////////////////采用CRC循环校验
/*unsignedchar*puchMsg;/*要进行CRC校验的消息*/
unsignedshortusDataLen;/*消息中字节数*/
/*CRC高位字节值表*/
staticunsignedcharauchCRCHi[]={
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,
0x80,0x41,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,
0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x00,0xC1,
0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x00,0xC1,
0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,
0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,
0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,
0x81,0x40,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,
0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,
0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x01,0xC0,
0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,
0x80,0x41,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,
0x80,0x41,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x01,0xC0,
0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,
0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,
0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,
0x80,0x41,0x00,0xC1,0x81,0x40
};
/*CRC低位字节值表*/
staticcharauchCRCLo[]={
0x00,0xC0,0xC1,0x01,0xC3,0x03,0x02,0xC2,0xC6,0x06,
0x07,0xC7,0x05,0xC5,0xC4,0x04,0xCC,0x0C,0x0D,0xCD,
0x0F,0xCF,0xCE,0x0E,0x0A,0xCA,0xCB,0x0B,0xC9,0x09,
0x08,0xC8,0xD8,0x18,0x19,0xD9,0x1B,0xDB,0xDA,0x1A,
0x1E,0xDE,0xDF,0x1F,0xDD,0x1D,0x1C,0xDC,0x14,0xD4,
0xD5,0x15,0xD7,0x17,0x16,0xD6,0xD2,0x12,0x13,0xD3,
0x11,0xD1,0xD0,0x10,0xF0,0x30,0x31,0xF1,0x33,0xF3,
0xF2,0x32,0x36,0xF6,0xF7,0x37,0xF5,0x35,0x34,0xF4,
0x3C,0xFC,0xFD,0x3D,0xFF,0x3F,0x3E,0xFE,0xFA,0x3A,
0x3B,0xFB,0x39,0xF9,0xF8,0x38,0x28,0xE8,0xE9,0x29,
0xEB,0x2B,0x2A,0xEA,0xEE,0x2E,0x2F,0xEF,0x2D,0xED,
0xEC,0x2C,0xE4,0x24,0x25,0xE5,0x27,0xE7,0xE6,0x26,
0x22,0xE2,0xE3,0x23,0xE1,0x21,0x20,0xE0,0xA0,0x60,
0x61,0xA1,0x63,0xA3,0xA2,0x62,0x66,0xA6,0xA7,0x67,
0xA5,0x65,0x64,0xA4,0x6C,0xAC,0xAD,0x6D,0xAF,0x6F,
0x6E,0xAE,0xAA,0x6A,0x6B,0xAB,0x69,0xA9,0xA8,0x68,
0x78,0xB8,0xB9,0x79,0xBB,0x7B,0x7A,0xBA,0xBE,0x7E,
0x7F,0xBF,0x7D,0xBD,0xBC,0x7C,0xB4,0x74,0x75,0xB5,
0x77,0xB7,0xB6,0x76,0x72,0xB2,0xB3,0x73,0xB1,0x71,
0x70,0xB0,0x50,0x90,0x91,0x51,0x93,0x53,0x52,0x92,
0x96,0x56,0x57,0x97,0x55,0x95,0x94,0x54,0x9C,0x5C,
0x5D,0x9D,0x5F,0x9F,0x9E,0x5E,0x5A,0x9A,0x9B,0x5B,
0x99,0x59,0x58,0x98,0x88,0x48,0x49,0x89,0x4B,0x8B,
0x8A,0x4A,0x4E,0x8E,0x8F,0x4F,0x8D,0x4D,0x4C,0x8C,
0x44,0x84,0x85,0x45,0x87,0x47,0x46,0x86,0x82,0x42,
0x43,0x83,0x41,0x81,0x80,0x40
};
unsignedcharuchCRCHi=0xFF;//高CRC字节初始化
unsignedcharuchCRCLo=0xFF;//低CRC字节初始化
unsigneduIndex;//CRC循环中的索引
while(usDataLen&&*puchMsg!
=-52)//传输消息缓冲区
{
uIndex=uchCRCHi^*puchMsg++;//计算CRC
uchCRCHi=uchCRCLo^auchCRCHi[uIndex];
uchCRCLo=auchCRCLo[uIndex];
}
return(uchCRCHi<<8|uchCRCLo)%2;
}
opinion.h
#defineACK00
#defineACK11
#defineRR-1
#defineRNR-2
#defineEND-3
#defineBag_Size1024/////////////////////报文段的信息量大小
classFRAME{
public:
FRAME(int,char*,int);
FRAME();
intnum;//当前的帧序号
boolcon;//控制字段
charmassage[Bag_Size];//报文段信息
intchecksum;//校验和
};
FRAME:
:
FRAME()
{;}
FRAME:
:
FRAME(inta,char*b,intc)
{
this->num=a;
strcpy(this->massage,b);
this->checksum=c;
this->con=true;
}
classBACK{
public:
BACK(bool,int);
boolR;//用来区分当前的响应帧究竟是正常响应还是拒绝true——期待;false——拒绝
intnum;//期待的帧或是拒绝的帧
};
BACK:
:
BACK(boola,intb)
{
this->R=a;
this->num=b;
}
/////////////////////////////////////////////////
//////////////////////////////////////////
intsend_size=5,receive_size=3;//////////用来标识发送、接收方的缓冲区大小,一般使用5:
3
intsend_num=0,receive_num=0;
intbag_size=1024;
ifstreamfin;
ofstreamfout;
boolflag=true;///////分别表示发送方可发,接收方可接
////////////////////////////////////////
dequesend_q;//最初文件分块的地方
queuereceive_q;//文件组装前地地方
dequesend_buf;///////////这个作为发送方的缓存
queuereceive_buf;
queuepath;/////////////////假想的两个线程之间的通信管道
queuereflect;///////////////假想的反馈通道
//////////////////////////////////////////////////////////////
receiver.h
boolreceive()////////////////用户从消息队列当中取出数据
{
boolflag1=true;
inti;
FRAMEx;
timer
(1);/////////////假想的1秒时延
receive_print();
for(i=0;ipath.empty();i++)
{
FRAMEx(path.front());
if(x.checksum!
=check_sum(x.massage)||x.num!
=receive_num)/////////帧差错或者是帧丢失
{
BACKa(true,receive_num);
reflect.push(a);
while(!
path.empty())
path.pop();//信道清除
returnfalse;
}
cout<<"\n\n\n\n"<<"帧数------------------------"<cout<fout.write(x.massage,1024);////////////正确接收
path.pop();//////////必须清除帧
receive_num++;
if(x.con==false){
BACKa(false,receive_num);
reflect.push(a);
while(!
path.empty())
path.pop();//信道清除
returnfalse;
}
}
while(!
path.empty())
path.pop();/////////////////////模拟不可超过接收方缓冲区大小,必须进行强制清空
BACKa(true,receive_num+1);
reflect.push(a);///////////////期待第receive_num+1帧
returntrue;
}
send_function.h
boolGetData()//文件分块进入一级队列//true表示通信继续false表示拆连开始
{
inti;
if(!
reflect.empty())
{
BACKa=reflect.front();
while(!
reflect.empty())
reflect.pop();
if(a.R==false)//拆连,默认传输成功
returnfalse;
else//确认帧销毁
{
i=send_buf.size()-send_num+a.num;//差值,进行递减
for(intj=1;j
send_buf.pop_front();
}
}
while(send_buf.size(){
charbuf[Bag_Size];
for(inti=0;ibuf[i]='\0';
fin.read(buf,Bag_Size);
FRAMEsend(send_num,buf,check_sum(buf));
if(fin.eof())
{
send.con=false;///////////////标志文件结尾
flag=false;
send_buf.push_back(send);
//send_q.push_back(send);////////////////规定新的东西只能从尾部插入
send_num++;//////////////////////////完成一次队列插入
returntrue;
}
//send_q.push_back(send);////////////////规定新的东西只能从尾部插入
send_buf.push_back(send);
send_num++;//////////////////////////完成一次队列插入
}
returntrue;
}
voidSendFrame()//分块进入缓冲栈和通道中
{
inti;
for(i=0;i{
//send_buf.push_back(send_q.front());/////////////缓冲压栈
path.push(send_buf.front());
send_buf.push_back(send_buf.front());
send_buf.pop_front();//////////////////原数据销毁
}
send_print(i);
}
table.h
voidsend_print(intj)
{
inti;
cout<<"\n发送端当前窗口:
"<cout<<"_________________________________________________"<for(i=0;icout<<"|"<<(i+send_num)%send_size;
cout<<"|\n_________________________________________________"<}
voidreceive_print()
{
inti;
cout<<"\n接收端当前窗口:
\n"<cout<<"_________________________________________________"<for(i=0;icout<<"|"<<(i+receive_num)%receive_size;
cout<<"|\n_________________________________________________"<cout<<"\n_________________________________________________"<cout<<"\n_________________________________________________"<}
timer.h
voidtimer(intx)//////////////////////////////////计时器函数
{
unsignedlongcnt=0,pre=0;
time_tt=time(NULL);
while(time(NULL)==t)pre++;
for(inti=1;i{
t=time(NULL);
while(time(NULL)==t)++cnt;
}
if(cnt)
{
cnt/=x-1;
while(cnt-->pre)time(NULL);
}
}
基本窗口:
实验截图:
D:
\课件\计算机网络\N_ARQ\2.txt
D:
\课件\计算机网络\N_ARQ\1.txt
0
100