📄 c++arqmoni.txt
字号:
void CPro7Dlg::OnTimer(UINT nIDEvent)
{
// TODO: Add your message handler code here and/or call default
switch(nIDEvent)
{
case ID_SEND_TIMER: //发送定时器被触发
if(m_sType==0)//当前的发送模式是正常发送模式
{
if((isNetEnable)&&(isToResend==-1)&&(!StopSend))
NetReady();//当网络层可用,没有要重发的帧,而且不在暂停状态,产生一个新的帧,并且发送
else{
if(isToResend!=-1)//有需要重发的帧
Resend();
}
if(nbuffer<m_SendWnd)//检验发送窗口是否已满,以此决定打开或者关闭网络层
isNetEnable=1;
else
isNetEnable=0;
}
if(m_sType==1)//当前的发送模式是错序发送模式
{
if(waitsend[point]!=-1)//按错序发送
{
SendFrame(waitsend[point]);
ShowFrame(waitsend[point]);
point++;
}
else
{
if(timerpoint<m_SendWnd) //错序发送完毕后依次打开重发定时器
start_timer(timerpoint++);
else//重发定时器全部打开后,这一批错序发送已经完毕,重新转入到正常的发送模式
m_sType=0;
}
}
break;
case ID_FRAME_TIMER1://重发定时器触发,记录下要重发的帧序号
isToResend=0;
break;
case ID_FRAME_TIMER2:
isToResend=1;
break;
case ID_FRAME_TIMER3:
isToResend=2;
break;
case ID_FRAME_TIMER4:
isToResend=3;
break;
case ID_FRAME_TIMER5:
isToResend=4;
break;
case ID_FRAME_TIMER6:
isToResend=5;
break;
case ID_FRAME_TIMER7:
isToResend=6;
break;
case ID_FRAME_TIMER8:
isToResend=7;
break;
}
ShowWndStatus();//更新界面显示的滑动窗口
CDialog::OnTimer(nIDEvent);
}
void CPro7Dlg::ReceiveFrame()
{
CString fk;//接收消息
CString sq;
CString in;
CString ck;
CString t;
CString str;
TCHAR temp[10]="\0";
char buf[5][255];
m_recv.Receive(buf,1275);
fk.Format("%s",buf[0]);
sq.Format("%s",buf[1]);
in.Format("%s",buf[2]);
ck.Format("%s",buf[3]);
t.Format("%s",buf[4]);
if(ck=="0")//ack或nak正常的到达
{
AddItem(nIndex,0,fk);//显示消息
AddItem(nIndex,1,sq);
AddItem(nIndex,2,in);
if(fk=="ack")
AddItem(nIndex,3,"ack arrived");
else
AddItem(nIndex,3,"nak arrived");
AddItem(nIndex++,4,t);
if(fk=="nak"&&between(ack_expected,atoi(sq),frame_to_send))//如果收到nak且序列号在窗口中,用变量记录下来,等待下一个时隙重发。
{
isToResend=atoi(sq);
}
else
{
if(fk=="ack")//收到确认,滑动窗口
{
while(between(ack_expected,atoi(sq),frame_to_send))
{
nbuffer=nbuffer-1;
stop_timer(ack_expected%m_SendWnd);
inc(ack_expected);
}
}
}
}
else
if(ck=="2")//确认消息在信道中丢失了
{
AddItem(nIndex,0,fk);
AddItem(nIndex,1,sq);
AddItem(nIndex,2,in);
AddItem(nIndex,3,"ack or nak lost");
AddItem(nIndex++,4,t);
}
ShowWndStatus();
}
接收方:
void CPro6Dlg::ReceiveFrame()
{
if(isReady)//当前处在可以接收数据包的状态
{
CString fk;
CString sq;
CString in;
CString ck;
CString t;
CString str;
TCHAR temp[10]="\0";
char buf[5][255];
m_recv.Receive(buf,1275);//接收数据包
fk.Format("%s",buf[0]);
sq.Format("%s",buf[1]);
in.Format("%s",buf[2]);
ck.Format("%s",buf[3]);
t.Format("%s",buf[4]);
isReady=FALSE;
AddItem(nIndex,0,fk);//显示数据包
AddItem(nIndex,1,sq);
AddItem(nIndex,2,in);
AddItem(nIndex,3,ck);
AddItem(nIndex,4,t);
nIndex++;
if(ck=="0")//如果到达的是一个完好的数据包
{
if(frame_expected!=atoi(sq)&&no_nak)
sendnak();//不是当前期望得到的数据包,有理由怀疑那一帧已经丢失或者损坏,所以要求重传
else//否则启动辅助定时器
start_ack_timer();
if(between(frame_expected,atoi(sq),too_far)&&//如果该帧的序列号在接收窗口内并且以前没有收到过该帧
(arrived[atoi(sq)%m_RecvWnd]==FALSE))
{
arrived[atoi(sq)%m_RecvWnd]=TRUE;//接收数据包
while(arrived[frame_expected%m_RecvWnd])//发现有按序到来的数据包则按需提交给网络层
{
CString str;
str.Format("%d",frame_expected);
str+=" write to disk";
AddItem(nIndex++,0,str);//由于是模拟协议,这里并没有真的提交,只是显示一下而已,但是只要将这四行代码换成写入硬盘的代码就可以实现。
no_nak=TRUE;//frame_expected已经提交,对下一个序列号的帧,显然没有发送过nak
arrived[frame_expected%m_RecvWnd]=FALSE;
inc(frame_expected);//滑动接收窗口
inc(too_far);
start_ack_timer();//启动辅助定时器
}
}
}
if(ck=="1")//接收到一个错误的帧,如果接受到被丢弃的帧,不做任何处理
{
if(no_nak) sendnak();
}
}
ShowWndStatus();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -