⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 stopwaitcommdlg.cpp

📁 停等协议 实现停等协议 利用发送端和接收端 利用串口
💻 CPP
📖 第 1 页 / 共 2 页
字号:
					pDlg->m_Send.EnableWindow(false);
					pDlg->m_Setup.EnableWindow(false);

					CommState=RECVSTATE;//进入接收状态
					Sequence=0;
					RecvPTR=0;
					STXFlag=0;
					TextLen=0;	

					time(&TimeStart);
					SendBuf[0]=ACK; //发送确认信息
					SendBuf[1]=Sequence;
					SendLen=2;	
					SendMsg("发送:ACK 0");
				}
				break;

			case SENDSTATE:
				if (ACKFlag==true)
				{
					if (RecvBuf[RecvPTR]==Sequence)
					{
						sprintf(DisplayStr,"接收:ACK %i",Sequence);pDlg->m_ListLog.InsertString(-1,DisplayStr);
						SendCount=0;
						pDlg->KillTimer(m_nTimer);//重新计时
						
						if (LastPacket==true)	//是否最后一包
						{
							CommState=IDLESTATE;
							SendFile.Close();	//最后一包,关闭文件

							SendBuf[0]=EOT; //通知接收方开始发送
							SendBuf[1]=EOT;
							SendLen=2;	
							SendMsg("发送:EOT");
							pDlg->m_ListLog.InsertString(-1,"------返回空闲状态------");
						
							time(&TimeFinish);	//显示统计信息
							DiffTime=difftime(TimeFinish,TimeStart);
							if (((ULONG) DiffTime)==0) sprintf(tempStr,"xxxxx");	//该程序只能精确到秒
							else
							{
								Ratio=(((TextLen*9.0)/Speed)/DiffTime)*100;
								sprintf(tempStr,"%f%%",Ratio);
							}
							pDlg->m_ListLog.InsertString(-1,"统计信息(注意本程序的传输时间只能精确到秒):");
							sprintf(DisplayStr,"数据速率:%i字节/秒;数据包长:%i字节;线路延迟:+%i微秒;",Speed,PacketLen,DelayTime);
							pDlg->m_ListLog.InsertString(-1,DisplayStr);
							sprintf(DisplayStr,"数据长度:%li字节;传输耗时:%li秒;传输效率:%s。",TextLen,(ULONG) DiffTime,tempStr);
							pDlg->m_ListLog.InsertString(-1,DisplayStr);
							pDlg->m_Send.EnableWindow(true);
							pDlg->m_Setup.EnableWindow(true);
						}
						else
						{
							MakePacket();
							SendMsg("发送:信息......");
							if(Sequence ==0 )Sequence=1;//变换Sequence.
							else Sequence=0;
							m_nTimer=pDlg->SetTimer(1,TIMEOUT,0);	//设置定时器
						}
					}
					ACKFlag=false;
				}
				else
					if (RecvBuf[RecvPTR]==ACK) ACKFlag=true;
				break;

			case RECVSTATE:
				switch (STXFlag)
				{
				  case 0:
				    	switch (RecvBuf[RecvPTR])
						{
						case EOT:
							CommState=IDLESTATE;RecvPTR=0;	//接收完成,连接断开
						pDlg->m_ListLog.InsertString(-1,"接收:完成");
						RecvFile.Close ();
						pDlg->m_ListLog.InsertString(-1,"------返回空闲状态------");
						pDlg->KillTimer(m_nTimer);

						time(&TimeFinish);	//显示统计信息
						DiffTime=difftime(TimeFinish,TimeStart);
						if (((ULONG) DiffTime)==0) sprintf(tempStr,"xxxxxx");	//该程序只能精确到秒
						else
						{
							Ratio=(((TextLen*9.0)/Speed)/DiffTime)*100;
							sprintf(tempStr,"%f%%",Ratio);
						}
						pDlg->m_ListLog.InsertString(-1,"统计信息(注意本程序的传输时间只能精确到秒):");
						sprintf(DisplayStr,"数据速率:%i字节/秒;数据包长:%i字节;线路延迟:+%i微秒;",Speed,PacketLen,DelayTime);
						pDlg->m_ListLog.InsertString(-1,DisplayStr);
						sprintf(DisplayStr,"数据长度:%li字节;传输耗时:%li秒;传输效率:%s。",TextLen,(ULONG) DiffTime,tempStr);
						pDlg->m_ListLog.InsertString(-1,DisplayStr);
						pDlg->m_Send.EnableWindow(true);
						pDlg->m_Setup.EnableWindow(true);
						break;
					case ENQ:
						pDlg->m_ListLog.InsertString(-1,"接收:ENQ");
						SendBuf[0]=ACK; SendBuf[1]=Sequence; SendLen=2;	//发送确认信息
						sprintf(DisplayStr,"发送:ACK %i",Sequence);
						SendMsg(DisplayStr);
						break;
					case STX:
						STXFlag=1;
						break;
					}
					break;

				case 1:
					if (RecvBuf[RecvPTR]==Sequence)
					{
						STXFlag=2;
						CRC=0;
					}
					else STXFlag=0;
					break;

				case 2:
					switch (RecvBuf[RecvPTR])
					{
					case ETX:
						if (CRC==0)
						{
							pDlg->m_ListLog.InsertString(-1,"接收:信息......");
							RecvFile.Write(RecvBuf,RecvPTR-1);	//将接收信息存入文件
							TextLen=TextLen+RecvPTR-1;
							
							if(Sequence==0)Sequence=1;
							else Sequence=0;
							
							SendBuf[0]=ACK; SendBuf[1]=Sequence; SendLen=2;
							sprintf(DisplayStr,"发送:ACK %i",Sequence);
							SendMsg(DisplayStr);
						}
						RecvPTR=0;STXFlag=0;	//开始新的一包
						break;
					default:
						if (RecvPTR < BUFFER_SIZE)	CRC=CRC^RecvBuf[RecvPTR++];
						else {RecvPTR=0;STXFlag=0;}
						break;
					}
					break;
				}
				break;
			} 
		}
	}
	return 0;
}

void MakePacket()	//打包
{
	int	len,i;	

	SendBuf[0]=STX;SendBuf[1]=Sequence;
	len=SendFile.Read(&SendBuf[2],PacketLen);	//读取数据
	
	CRC=0;	//计算校验和
	for (i=0;i<len;i++)
		CRC=CRC^SendBuf[i+2];
	
	SendBuf[2+len]=CRC;
	SendBuf[2+len+1]=ETX;

	SendLen=2+1+len+1;
	if(len==PacketLen)LastPacket=false;
	else LastPacket=true;
	TextLen=TextLen+len;
}

void SendMsg(char *DisplayStr)	//向串行口发送信息
{
	CEvent		SendEvent(0,TRUE,0,0);	//发送和接收事件
	OVERLAPPED	SendOV;
	ULONG		SentLen;

	memset(&SendOV,0,sizeof(SendOV));	//初始化Overlapped变量
	SendOV.hEvent=SendEvent;

	Sleep(DelayTime);		//模拟长线路延迟

	WriteFile(m_hCommPort,SendBuf,SendLen,&SentLen,&SendOV);
	GetOverlappedResult(m_hCommPort,&SendOV,&SentLen,TRUE);		//等待发送完成
	SendEvent.ResetEvent();
	pDlg->m_ListLog.InsertString(-1,DisplayStr);	//显示信息
}

void CStopWaitCommDlg::OnCancel() 
{
	// TODO: Add extra cleanup here
	
	CDialog::OnCancel();
}

void CStopWaitCommDlg::OnSetup() 
{
	// TODO: Add your control notification handler code here
	
}

void CStopWaitCommDlg::OnTimer(UINT nIDEvent) 
{
	// TODO: Add your message handler code here and/or call default
	switch (CommState)
	{
	case SENDSTATE:
		if (SendCount<3)
		{
			SendCount++;
			KillTimer(m_nTimer);
			SendMsg("超时重传......");
			m_nTimer=SetTimer(1,TIMEOUT,NULL);
		}
		else
		{
			pDlg->KillTimer(m_nTimer);
			m_ListLog.InsertString(-1,"发送超时......");
			CommState=IDLESTATE;
			SendFile.Close();	//最后一包,关闭文件
			SendBuf[0]=EOT;SendBuf[1]=EOT;SendLen=2;	//通知接收方开始发送
			SendMsg("发送:EOT");
			m_ListLog.InsertString(-1,"------返回空闲状态------");
			m_Send.EnableWindow(true);
			m_Setup.EnableWindow(true);
		}
		break;
	case RECVSTATE:
		m_ListLog.InsertString(-1,"接收超时......");
		CommState=IDLESTATE;RecvPTR=0;	//接收完成,连接断开
		pDlg->m_ListLog.InsertString(-1,"接收:完成");
		RecvFile.Close ();
		m_ListLog.InsertString(-1,"------返回空闲状态------");
		KillTimer(m_nTimer);
		m_Send.EnableWindow(true);
		m_Setup.EnableWindow(true);
		break;
	}
	CDialog::OnTimer(nIDEvent);
}
bool SetupCommPort()	//设置串行口
{
	
	DCB	CommDCB;	//串行口的设备控制块
	

		m_hCommPort=CreateFile (CommPort,		//打开串行口
			GENERIC_READ|GENERIC_WRITE,
			0,
			NULL,
			OPEN_EXISTING,
			FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED,
			NULL);
		if(m_hCommPort==INVALID_HANDLE_VALUE)
		{
			AfxMessageBox("系统无法打开此串口设备(CreateFile)!");
			return false;
		}
		
		AfxBeginThread(ReadChar,NULL,THREAD_PRIORITY_NORMAL);

	
	if(!GetCommState(m_hCommPort,&CommDCB)) //得到原来的串口参数
	{
		AfxMessageBox("无法得到串口状态(GetCommState)!");
		CloseHandle(m_hCommPort);
		return false;
	}
	
	CommDCB.BaudRate =Speed;	//设置新的串口参数
	CommDCB.ByteSize =8; 
	CommDCB.Parity = NOPARITY; 
    CommDCB.StopBits = ONESTOPBIT ;
	CommDCB.fBinary = TRUE ;
	CommDCB.fParity = FALSE; 
	
   	if(!SetCommState(m_hCommPort, &CommDCB))
	{
		AfxMessageBox("无法设置串口状态(SetupCommState)!");
		CloseHandle(m_hCommPort);
		return false;
	} 
	
	if (!SetupComm(m_hCommPort,BUFFER_SIZE,BUFFER_SIZE))		//设置缓冲区
	{
		AfxMessageBox("设置缓冲区错误(SetupComm)!");
		CloseHandle(m_hCommPort);
		return false;
	}
	if (!PurgeComm(m_hCommPort, PURGE_RXCLEAR|PURGE_TXCLEAR|PURGE_RXABORT|PURGE_TXABORT)) //清除所有接收和发送缓冲区中的数据
	{
		AfxMessageBox("清空缓冲区错误(PurgeComm)!");
		CloseHandle(m_hCommPort);
		return false;
	}
	RecvPTR=0;
	return true;
}

void CStopWaitCommDlg::OnClose() 
{
	// TODO: Add your message handler code here and/or call default
	CloseHandle(m_hCommPort);
	CDialog::OnClose();
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -