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

📄 excute.cpp

📁 tftp功能服务器及客户端的实现
💻 CPP
📖 第 1 页 / 共 2 页
字号:
				timeFormat,inet_ntoa(RcvAddr.sin_addr),RcvPort,fileandmode);
		::SendMessage(tftpHwnd,WM_DATADISPLAY,0,(LPARAM)strDisplay);
		fwrite(strDisplay,1,strlen(strDisplay),stream);
		
		b=0;
		AckBuf  ABuf;
		DataBuf DBuf;
		ABuf.pcode = htons(ACK);
		DBuf.pcode = htons(DAT);
		//测试打开请求下载文件
		if((pFile = fopen(fileandmode,"r"))!=NULL)
		{	
			//请求文件存在,拒绝覆盖可以保护用户文件覆盖掉 server 上的文件
			SendErrors(6);

			timeNow = CTime::GetCurrentTime();   
			timeFormat=timeNow.Format("%H:%M:%S");

			sprintf(strDisplay,"%s : 服务器存在同名文件 : %s,中止[%s:%d]!\n",
				timeFormat,fileandmode,inet_ntoa(RcvAddr.sin_addr),RcvPort);
			::SendMessage(tftpHwnd,WM_DATADISPLAY,0,(LPARAM)strDisplay);
			fwrite(strDisplay,1,strlen(strDisplay),stream);
			fclose(pFile);
			return;
		}
		CFile *pCFile1;
		//请求文件不存在,为 Client 创建文件
		pCFile1 = new CFile((LPCTSTR)fileandmode, CFile::modeCreate|CFile::modeWrite);
		
		char RcvBuf[1024];

		fd_set SockSet;
		while(1)
		{
			memset(DBuf.buf,0,sizeof(DBuf.buf));
		
			ABuf.block = htons(b);

			timeNow=CTime::GetCurrentTime();   
			timeFormat=timeNow.Format("%H:%M:%S");
			sprintf(strDisplay,"%s : 回送 [%s:%d] 第 %d 号 ACK\n",
				timeFormat,inet_ntoa(RcvAddr.sin_addr),RcvPort,b);
			::SendMessage(tftpHwnd,WM_DATADISPLAY,0,(LPARAM)strDisplay);
			fwrite(strDisplay,1,strlen(strDisplay),stream);
			while(1)
			{
				//发送ACK
				memset(DBuf.buf,0,sizeof(DBuf.buf));
				sendto(SrvSocket,(char*)&ABuf,
					sizeof(ABuf),0,(SOCKADDR*)&RcvAddr,len);
			
				FD_ZERO(&SockSet);
				FD_SET(SrvSocket,&SockSet);
				if(select(SrvSocket,&SockSet,NULL,NULL,&TVal))
				{
					nBytesRcv = recvfrom(SrvSocket,RcvBuf,
						sizeof(RcvBuf),0,(SOCKADDR *)&RcvAddr,&len);
					nBytesRcv -= 4;

					timeNow=CTime::GetCurrentTime();   
					timeFormat=timeNow.Format("%H:%M:%S");

					if(u_short(ntohs(ABuf.block) + 1) != u_short(ntohs(((DataBuf*)RcvBuf)->block)) || 
						ntohs(((DataBuf*)RcvBuf)->pcode) != DAT)
					{
						//DATA 序列号出错,或不是 DATA 包处理
						if(((ErrorBuf*)RcvBuf)->pcode == ntohs(ERR))
						{
							SetErrMsg(ntohs(((ErrorBuf*)RcvBuf)->ErrorCode));
							return;
						}
						if(timeout == 5)
						{
							//重复五次错误 DATA, 中止服务
							sprintf(strDisplay,"%s : 中止 [%s:%d], 出错重发第 %d 号ACK %d 次\n",
							timeFormat,inet_ntoa(RcvAddr.sin_addr),RcvPort,b,timeout);
							::SendMessage(tftpHwnd,WM_DATADISPLAY,0,(LPARAM)strDisplay);
							fwrite(strDisplay,1,strlen(strDisplay),stream);
							timeout = 0;
							delete pCFile1;
							return;
						}
						
						timeNow=CTime::GetCurrentTime();   
						timeFormat=timeNow.Format("%H:%M:%S");
						sprintf(strDisplay,"%s : 收到 [%s:%d] 第 %d 号 DATA, 重发第 %d 次 ACK\n",timeFormat,
							inet_ntoa(RcvAddr.sin_addr),RcvPort,ntohs(((DataBuf*)RcvBuf)->block),timeout);
						::SendMessage(tftpHwnd,WM_DATADISPLAY,0,(LPARAM)strDisplay);
						fwrite(strDisplay,1,strlen(strDisplay),stream);
						timeout++;
						continue;
					}
					else//right datagram
					{
						sprintf(strDisplay,"%s : 收到 [%s:%d] 第 %d 号 DATA,%d Bytes\n",timeFormat,
						inet_ntoa(RcvAddr.sin_addr),RcvPort,ntohs(((DataBuf*)RcvBuf)->block),nBytesRcv);
						::SendMessage(tftpHwnd,WM_DATADISPLAY,0,(LPARAM)strDisplay);
						fwrite(strDisplay,1,strlen(strDisplay),stream);

						TotalBytes += nBytesRcv;
						pCFile1->Write(((DataBuf*)RcvBuf)->buf,nBytesRcv);
						b = ntohs(((DataBuf*)RcvBuf)->block);
						if(nBytesRcv < 512)
						{	
							//最后一个包,传送完成
							ABuf.block = htons(b);
							sendto(SrvSocket,(char*)&ABuf,
								sizeof(ABuf),0,(SOCKADDR*)&RcvAddr,len);
							
							timeNow=CTime::GetCurrentTime();   
							timeFormat=timeNow.Format("%H:%M:%S");
							sprintf(strDisplay,"%s : 回送 [%s:%d] 第 %d 号 ACK",
								timeFormat,inet_ntoa(RcvAddr.sin_addr),RcvPort,b);
							::SendMessage(tftpHwnd,WM_DATADISPLAY,0,(LPARAM)strDisplay);
							fwrite(strDisplay,1,strlen(strDisplay),stream);

							delete pCFile1;

							timeNow=CTime::GetCurrentTime();   
							timeFormat=timeNow.Format("%H:%M:%S");

							TotalTime -= timeNow.GetHour();
							if(TotalTime <= 0)
								TotalTime = TotalTime * 60;//传文件时间不得超过24小时,									
							else						   //否则检查不出正确耗时
								TotalTime = 24 * 60;
							TotalTime += timeNow.GetMinute() - StartTime.GetMinute();
							TotalTime = TotalTime * 60;

							TotalTime += timeNow.GetSecond() - StartTime.GetSecond();
							if(TotalTime == 0)
								TotalTime = 1;
							sprintf(strDisplay,"%s : [%s:%d]%s上传完毕: %d Bytes int %d seconds, %d Bytes/s.\n",
									timeFormat,inet_ntoa(RcvAddr.sin_addr),RcvPort,fileandmode,TotalBytes,TotalTime,int(TotalBytes/TotalTime));
							::SendMessage(tftpHwnd,WM_DATADISPLAY,0,(LPARAM)strDisplay);
							fwrite(strDisplay,1,strlen(strDisplay),stream);
							delete pCFile1;
							fclose(stream);
							return;
						}
						timeout = 1;
						break;
					}
				}
				else
				{
					if(timeout == 5)
					{
						//重复五次 select 超时,中止服务
						delete pCFile1;
						timeout = 0;
						sprintf(strDisplay,"%s : 接收 [%s:%d] 第 %d 号 DATA 超时,中止服务!\n",timeFormat,
							inet_ntoa(RcvAddr.sin_addr),RcvPort,ntohs(((DataBuf*)RcvBuf)->block)+1);
						::SendMessage(tftpHwnd,WM_DATADISPLAY,0,(LPARAM)strDisplay);
						fwrite(strDisplay,1,strlen(strDisplay),stream);
						return;
					}
					timeout++;
				}		
			}//if select
		}//while(1)
		break;

	default: 
		SendErrors(0);
		fclose(stream);
		return;
	}

}

void Cexcute::SendErrors(u_short m_ErrorNum)
{
	ErrorBuf EBuf;
	memset(EBuf.ErrMsg,0,100);
	EBuf.pcode = htons(ERR);
	switch(m_ErrorNum)
	{
	case 0:
		strcpy(EBuf.ErrMsg,"Not defined, see error message (if any).\n");
		EBuf.ErrorCode = htons(0);		
		break;
	case 1:
		strcpy(EBuf.ErrMsg,"File not found.\n");
		EBuf.ErrorCode = htons(1);
		break;
	case 2:
		strcpy(EBuf.ErrMsg,"Access violation.\n");
		EBuf.ErrorCode = htons(2);
		break;
	case 3:
		strcpy(EBuf.ErrMsg,"Disk full or allocation exceeded.\n");
		EBuf.ErrorCode = htons(3);
		break;
	case 4:
		strcpy(EBuf.ErrMsg,"Illegal TFTP operation.\n");
		EBuf.ErrorCode = htons(4);
		break;
	case 5:
		strcpy(EBuf.ErrMsg,"Unknown transfer ID.\n");
		EBuf.ErrorCode = htons(5);
		break;
	case 6:
		strcpy(EBuf.ErrMsg,"File already exists.\n");
		EBuf.ErrorCode = htons(6);
		break;
	case 7:
		strcpy(EBuf.ErrMsg,"No such user.\n");
		EBuf.ErrorCode = htons(7);
		break;
	}
	sendto(SrvSocket,(char *)&EBuf,sizeof(ErrorBuf),0,(SOCKADDR*)&RcvAddr,len);
}
//线程结束时,删除存在节点的记录
void Cexcute::DeleteRQ(SOCKADDR_IN RcvAddr)
{
	ExistRQ * tmp, *bftmp;
	bftmp = RQHead;
	tmp = bftmp;
	while(tmp != NULL)
	{
		if(RcvAddr.sin_port == tmp->m_Port &&
			RcvAddr.sin_addr.S_un.S_addr == tmp->m_Addr.S_un.S_addr)
		{
			if(bftmp == RQHead)
				RQHead = tmp->next;
			else
				bftmp->next = tmp->next;
			
			delete tmp;
		}
		else
		{
			bftmp = tmp;
			tmp=tmp->next;
		}
	}
}
//显示错误信息函数
void Cexcute::SetErrMsg(u_short ErrNum)
{
	switch(ErrNum)
	{
	case 0:
		sprintf(strDisplay,"Not defined, see error message (if any).\n");		
		break;
	case 1:
		sprintf(strDisplay,"Server Error: File not found.\n");
		break;
	case 2:
		sprintf(strDisplay,"Access violation.\n");
		break;
	case 3:
		sprintf(strDisplay,"Disk full or allocation exceeded.\n");
		break;
	case 4:
		sprintf(strDisplay,"Illegal TFTP operation mode.\n");
		break;
	case 5:
		sprintf(strDisplay,"Unknown transfer ID.\n");
		break;
	case 6:
		sprintf(strDisplay,"Server Error: File already exists.\n");
		break;
	case 7:
		sprintf(strDisplay,"No such user.\n");
		break;
	}
		::SendMessage(tftpHwnd,WM_DATADISPLAY,0,(LPARAM)strDisplay);
}

⌨️ 快捷键说明

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