?? 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 + -