ARQ协议的实现一.实验目的要求学生掌握Socket编程及ARQ协议实验内容1.必须采用应答机制、超时计数器技术、帧编号技术、重传技术2.校验和技术可选,校验和s的计算:设要发送n字节,bi为第i个字,s=(b0+b1+…+bn)mod2563.在接收端,设置随机数,根据随机数执行相关操作,0代表正常,1代表帧丢失,2代表帧出错,3代表应答帧丢失(即不发生应答帧)4.使用图形界面,发送端:显示发送的数据、是否重传、本次帧序号、接收到的应答帧的序号接收端:显示接收到的数据、本次帧序号、本次随机选择的出错情况、发送应答帧的序号、是否重复实验流程1.发送端打开窗口,准备发送数据,服务器端启动设备,打开端口,监听各个端口,采用的是多路复用技术,大大缓解了网络阻塞问题2.服务器端设置随机出错状态3.客户端点击发送数据(如果发送的数据没有收到应答的帧超过5个,即发送窗口已满,不再发送)4.正常情况下服务器端会收到数据并发送应答帧,帧或应答帧丢失时或帧出错时丢弃,客户端会启动超时重传,5.数据发送完毕后关闭关键技术1.流套接字:流套接字(SOCK_STREAM):流套接字用于提供面向连接、可靠的数据传输服务。该服务将保证数据能够实现无差错、无重复发送,并按顺序接收。流套接字之所以能够实现可靠的数据服务,原因在于其使用了传输控制协议,即TCP(TheTransmissionControlProtocol)协议。多路复用技术IntPASCALFARWSAAsyncSelect(SOCKETs,HWNDhWnd,unsignedintwMsg,longlEvent);本函数用来请求WindowsSocketsDLL为窗口句柄发一条消息-无论它何时检测到由lEvent参数指明的网络事件.要发送的消息由wMsg参数标明.被通知的套接口由s标识.ARQ协议选择重传(AutomaticRepeat-reQuest,ARQ)是OSI模型中数据链路层的错误纠正协议之一。它包括停止等待ARQ协议和连续ARQ协议,错误侦测(ErrorDetection)、正面确认(PositiveAcknowledgment)、逾时重传(RetransmissionafterTimeout)与负面确认继以重传(NegativeAcknowledgmentandRetransmission)等机制。MFC技术MFC(MicrosoftFoundationClasses),是一个微软公司提供的类库(classlibraries),以C++类的形式封装了Windows的API,并且包含一个应用程序框架,以减少应用程序开发人员的工作量。其中包含的类包含大量Windows句柄封装类和很多Windows的内建控件和组件的封装类五.源代码1.client:WORDCCClientDlg::CRC(unsignedchar*p,intlen){WORDcrc=0;unsignedchari;while(len--){for(i=0x80;i!=0;i=i1){if((crc&0x8000)!=0){crc=crc1;crc=crc^0x1021;}else{crc=crc1;}if((*p&i)!=0){crc=crc^0x1021;}}p++;}returncrc;}voidCCClientDlg::OnOk(){//TODO:Addyourcontrolnotificationhandlercodehereif(judgeFirst){if(ListNum=5){MessageBox(发送窗口大于5!);}else{ret=send(m_hSocket,(char*)buf[NumSend],buf[NumSend][0],0);ListNum++;if(ret!=buf[NumSend][0]){TRACE(SendError:%d\n,WSAGetLastError());return;}pos[timerNum]=0;m_Timer[timerNum]=SetTimer(timerNum+1,1000,NULL);timerNum=(timerNum+1)%8;NumSend=(NumSend+1)%8;charstr[10];itoa(NumSend,str,10);m_Stc_Send=str;UpdateData(FALSE);}}else{MessageBox(请准备好发送帧!);}}voidCCClientDlg::StartUp(){WSADATAwsadata;WORDversion=MAKEWORD(2,0);intret=WSAStartup(version,&wsadata);if(ret!=0){TRACE(InitializeError!\n);}}voidCCClientDlg::OnConfig(){//TODO:AddyourcontrolnotificationhandlercodehereUpdateData(TRUE);inti=0;CStringdata[8];data[0]=m_Data1;data[1]=m_Data2;data[2]=m_Data3;data[3]=m_Data4;data[4]=m_Data5;data[5]=m_Data6;data[6]=m_Data7;data[7]=m_Data8;for(i=0;i8;i++){if(data[i]==){MessageBox(请讲帧填写完整!);return;}}for(i=0;i8;i++){intstrNum;unsignedchar*fell;fell=(unsignedchar*)data[i].GetBuffer(0);crc=CRC(fell,data[i].GetLength());strNum=data[i].GetLength();buf[i]=newunsignedchar[strNum+4];buf[i][0]=(char)(data[i].GetLength()+4);for(intj=1;j=strNum;j++)buf[i][j]=data[i][j-1];buf[i][j]=HIBYTE(crc);buf[i][j+1]=LOBYTE(crc);buf[i][j+2]=(char)i;//MessageBox(str);}m_Start=0;m_End=i-1;UpdateData(FALSE);if(m_hSocket!=NULL){closesocket(m_hSocket);m_hSocket=NULL;}if(m_hSocket==NULL){m_hSocket=socket(AF_INET,SOCK_STREAM,0);ASSERT(m_hSocket!=NULL);}CStringSeverIp;SeverIp=127.0.0.1;m_addr.sin_family=AF_INET;m_addr.sin_port=htons(1314);m_addr.sin_addr.S_un.S_addr=inet_addr(SeverIp.GetBuffer(0));ret=connect(m_hSocket,(LPSOCKADDR)&m_addr,sizeof(m_addr));if(ret==SOCKET_ERROR){TRACE(ConnectError:%d\n,(error=WSAGetLastError()));if(error==10061)AfxMessageBox(_T(连接失败!));return;}judgeFirst=1;m_Stc_Send=0;UpdateData(FALSE);WSAAsyncSelect(m_hSocket,AfxGetMainWnd()-m_hWnd,WM_MY_MESSAGE,FD_READ);this-InitProg();}voidCCClientDlg::CleanUp(){if(WSACleanup()!=0){TRACE(UnInitializeError:%d\n,WSAGetLastError());}}voidCCClientDlg::OnCancel(){//TODO:Addyourcontrolnotificationhandlercodehereif(m_hSocket!=NULL){closesocket(m_hSocket);m_hSocket=NULL;}CDialog::OnCancel();}voidCCClientDlg::OnDestroy(){CDialog::OnDestroy();//TODO:AddyourmessagehandlercodehereCleanUp();}voidCCClientDlg::BackStc(intm,inttype){if(!type)switch(m){case0:m_Stc1=重传;break;case1:m_Stc2=重传;break;case2:m_Stc3=重传;break;case3:m_Stc4=重传;break;case4:m_Stc5=重传;break;case5:m_Stc6=重传;break;case6:m_Stc7=重传;break;case7:m_Stc8=重传;break;}elseswitch(m){case0:m_Stc1=不重传;break;case1:m_Stc2=不重传;break;case2:m_Stc3=不重传;break;case3:m_Stc4=不重传;break;case4:m_Stc5=不重传;break;case5:m_Stc6=不重传;break;case6:m_Stc7=不重传;break;case7:m_Stc8=不重传;break;}}voidCCClientDlg::setProg(intm){switch(m){case0:m_Prog1.SetPos(pos[m]);break;case1:m_Prog2.SetPos(pos[m]);break;case2:m_Prog3.SetPos(pos[m]);break;case3:m_Prog4.SetPos(pos[m]);break;case4:m_Prog5.SetPos(pos[m]);break;case5:m_Prog6.SetPos(pos[m]);break;case6:m_Prog7.SetPos(pos[m]);break;case7:m_Prog8.SetPos(pos[m]);break;}}voidCCClientDlg::OnTimer(UINTnIDEvent){//TODO:Addyourmessagehandlercodehereand/orcalldefaultCDialog::OnTimer(nIDEvent);intnum;num=nIDEvent-1;if(pos[num]=30){ret=send(m_hSocket,(char*)buf[num],buf[num][0],0);BackStc(num,0);UpdateData(FALSE);pos[num]=0;if(ret!=buf[num][0]){TRACE(SendError:%d\n,WSAGetLastError());return;}}else{pos[num]++;setProg(num);}}voidCCClientDlg::InitProg(){m_Prog1.SetRange(0,30);m_Prog1.SetStep(1);m_Prog2.SetRange(0,30);m_Prog2.SetStep(1);m_Prog3.SetRange(0,30);m_Prog3.SetStep(1);m_Prog4.SetRange(0,30);m_Prog4.SetStep(1);m_Prog5.SetRange(0,30);m_Prog5.SetStep(1)