📄 excute.cpp
字号:
// excute.cpp: implementation of the Cexcute class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "TftpSrv.h"
#include "excute.h"
#include <stdio.h>
#include <string.h>
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
Cexcute::Cexcute(u_short pcode,char *fileandmode,SOCKADDR_IN RcvAddr,HWND hwnd)
{
this->pcode=pcode;
this->fileandmode=fileandmode;
this->RcvAddr=RcvAddr;
this->tftpHwnd = hwnd;
this->PortCount = (u_short)6006;
this->TotalTime = 0;
this->RcvPort = htons(RcvAddr.sin_port);
len = sizeof(SOCKADDR);
TVal.tv_sec = 5;
TVal.tv_usec =0;
Init();
char *szLogPath = "D:\\TftpSrvLog";
CreateDirectory(szLogPath,NULL);
//list[200] 设置 LOg 文件路径,log文件名由客户端主机ip及请求文件和请求方式组成
char list[200];
if(pcode == RRQ)
sprintf(list,"D:\\TftpSrvLog\\%s.RRQ %s.log",inet_ntoa(RcvAddr.sin_addr),fileandmode);
else if(pcode == WRQ)
sprintf(list,"D:\\TftpSrvLog\\%s.WRQ %s.log",inet_ntoa(RcvAddr.sin_addr),fileandmode);
//打开创建 Log 文件
if(pcode == RRQ || pcode == WRQ)
stream = fopen(list,"a+");
if(stream == NULL)
{
AfxMessageBox("初始化log文件失败");
fclose( stream );
}
//写 log 头部
if(pcode == RRQ)
{
sprintf(list,"-------------------------RRQ %s--------------------------\n",fileandmode);
fwrite(list,1,strlen(list),stream);
}
else if(pcode == WRQ)
{
sprintf(list,"-------------------------WRQ %s---------------------------\n",fileandmode);
fwrite(list,1,strlen(list),stream);
}
SendMessage();
}
Cexcute::~Cexcute()
{
}
//Init 新创建进程套接字初始化
BOOL Cexcute::Init()
{
SrvSocket = socket(AF_INET,SOCK_DGRAM,0);
if(SrvSocket == INVALID_SOCKET)
{
AfxMessageBox("socket erro");
return FALSE;
}
SrvAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
SrvAddr.sin_family = AF_INET;
SrvAddr.sin_port = htons(PortCount++);
if(INVALID_SOCKET ==(bind(SrvSocket,(SOCKADDR*)&SrvAddr,sizeof(SrvAddr))))
{
return Init();
}
return TRUE;
}
//SendMessage 收发文件函数
void Cexcute::SendMessage()
{
StartTime = GetCurrentTime();
TotalTime = StartTime.GetHour();
timeFormat = StartTime.Format("%H:%M:%S");
size_t nBytesRcv = 0;
size_t TotalBytes = 0;
u_short b = 0;
int timeout = 0;
int Repeat = 0;
int OpcodeErr = 1;
switch(pcode)
{
//========================下载文件请求 RRQ==================
case RRQ :
sprintf(strDisplay,"%s : [%s%d] 请求下载文件 %s,连接成功!\n",
timeFormat,inet_ntoa(RcvAddr.sin_addr),RcvPort,fileandmode);
::SendMessage(tftpHwnd,WM_DATADISPLAY,0,(LPARAM)strDisplay);
fwrite(strDisplay,1,strlen(strDisplay),stream);
DBuf.pcode = htons(DAT);
if((pFile = fopen(fileandmode,"r"))==NULL)
{ //请求文件不存在,中止服务
SendErrors(1);
timeNow=CTime::GetCurrentTime();
timeFormat=timeNow.Format("%H:%M:%S");
sprintf(strDisplay,"%s : [RRQ %s] 服务器找不到请求文件,停止!\n",
timeFormat,fileandmode);
::SendMessage(tftpHwnd,WM_DATADISPLAY,0,(LPARAM)strDisplay);
fwrite(strDisplay,1,strlen(strDisplay),stream);
fclose(stream);
return ;
}
fclose(pFile);
CFile *pCFile;
pCFile=new CFile((LPCTSTR)fileandmode, CFile::modeRead);
size_t nBytesRead;
size_t SendBuf;
while(1)//发送数据
{
memset(DBuf.buf,0,512);
//读文件数据,默认二进制格式
nBytesRead = pCFile->Read(DBuf.buf, 512);
TotalBytes += nBytesRead;
DBuf.block = htons(++b); //设置网络字节序的数据包序列号
fd_set SockSet;
SendBuf = nBytesRead + 4;//发送数据的总长度,由4字节的block
//和opcode和实际的数据组成
timeNow=CTime::GetCurrentTime();
timeFormat=timeNow.Format("%H:%M:%S");
sprintf(strDisplay,"%s : 给 [%s:%d] 发送第 %d 号 DATA %d Bytes\n",
timeFormat,inet_ntoa(RcvAddr.sin_addr),RcvPort,b,nBytesRead);
::SendMessage(tftpHwnd,WM_DATADISPLAY,0,(LPARAM)strDisplay);
fwrite(strDisplay,1,strlen(strDisplay),stream);
while(1)//超时循环
{
sendto(SrvSocket,(char*)&DBuf,SendBuf,0,
(SOCKADDR*)&RcvAddr,len);
FD_ZERO(&SockSet);
FD_SET(SrvSocket,&SockSet);
if(select(SrvSocket,&SockSet,NULL,NULL,&TVal))
{ //select 函数限制套接字的 recvfrom 阻塞时间,此处为 5 s
recvfrom(SrvSocket,(char*)&ABuf,sizeof(AckBuf),
0,(SOCKADDR*)&RcvAddr,&len);
if(ntohs(ABuf.pcode) != ACK || ntohs(ABuf.block) != b)
{
//收到不正确包的处理:重发报文再次接受
Repeat++;
timeNow=CTime::GetCurrentTime();
timeFormat=timeNow.Format("%H:%M:%S");
if(Repeat == 5)
{ //重复收取不正确包 5 次,则中止服务
timeNow=CTime::GetCurrentTime();
timeFormat=timeNow.Format("%H:%M:%S");
sprintf(strDisplay,"%s : 给 [%s:%d] 重发第 %d 号 DATA 第 %d 次,中止服务.\n",
timeFormat, inet_ntoa(RcvAddr.sin_addr),RcvPort,b,Repeat);
::SendMessage(tftpHwnd,WM_DATADISPLAY,0,(LPARAM)strDisplay);
fwrite(strDisplay,1,strlen(strDisplay),stream);
Repeat = 0;
delete pCFile;
return;
}
sprintf(strDisplay,"%s : 给 [%s:%d] 重发第 %d 号 DATA 第 %d 次\n",
timeFormat, inet_ntoa(RcvAddr.sin_addr),RcvPort,b,Repeat);
::SendMessage(tftpHwnd,WM_DATADISPLAY,0,(LPARAM)strDisplay);
fwrite(strDisplay,1,strlen(strDisplay),stream);
continue;
}
else {
//收到正确的 ACK 处理
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);
if(nBytesRead<512)
{
//发送的数据包为最后一个,传送完成处理
timeNow=CTime::GetCurrentTime();
pCFile->Close();
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]: %ld Bytes,时间: %d s, %d Bytes/s\n",fileandmode,
inet_ntoa(RcvAddr.sin_addr),RcvPort,TotalBytes,TotalTime,u_int(TotalBytes/TotalTime));
::SendMessage(tftpHwnd,WM_DATADISPLAY,0,(LPARAM)strDisplay);
fwrite(strDisplay,1,strlen(strDisplay),stream);
delete pCFile;
fclose(stream);
return;
}
break;
}
}
else//if select
{
//select 超时处理
if(5 == timeout)
{
//连续超时 5 次,中止服务
timeNow=CTime::GetCurrentTime();
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 pCFile;
return;
}
timeNow=CTime::GetCurrentTime();
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);
memset((void*)&ABuf,0,sizeof(ABuf));
}
}//if select
}//while(1)
break;
//============================上传文件请求 WRQ==================
case WRQ :
//提示连接成功
sprintf(strDisplay,"%s [%s:%d]请求上载文件 %s,连接成功!\n",
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -