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

📄 dspfile.cpp

📁 DSP应用实例(一)--轻松实现BT多点下载 源码
💻 CPP
字号:
// DSPFile.cpp: implementation of the DSPFile class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "DSPFile.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

enum
{
	SEND_SUCCESSFUL=100,
	RECV_SUCCESSFUL,
	SEND_TIMEOUT,
	RECV_TIMEOUT,
	SEND_FAIL,
	RECV_FAIL,
	SEND_ABORT,
	RECV_ABORT,
};


DSPFile::DSPFile()
{
}

DSPFile::~DSPFile()
{
	if(this->m_ifs.is_open())
		this->m_ifs.close();
	if(this->m_ofs.is_open())
	{
		this->m_ofs.flush();
		this->m_ofs.close();
	}
}

bool DSPFile::Serialize(BYTE byClassLevels,BYTE byAttrNo,DSP::_DSPPACKET &dsp)
{
	switch(byAttrNo)
	{
		case 1:
			dsp.Write(this->m_nFilesize);
			return false;
		case 2:
			dsp.Write(this->m_strFilename);
			return false;
		case 3:						//序列化最后一个属性
			if(this->m_ifs.is_open()==FALSE)
			{
				//打开文件准备读
				if(DSP::OpenIfstreamForRead(this->m_ifs,this->m_hFileDetail.strPathname)==FALSE)
				{
					//如果打开文件失败
					dsp.Write(NULL,0,true);
					return true;
				}
			}
			else
			{
				//如果文件已经读完
				this->m_ifs.close();
			}
			dsp.Write(this->m_buff,FILE_SECT_SIZE,false);
	}

	return true;
}

bool DSPFile::UnSerialize(BYTE byClassLevels,BYTE byAttrNo,DSP::_DSPPACKET &dsp,DWORD dwLen)
{
	//反序列化对象
	switch(byAttrNo)
	{
		case 1:
			dsp.Read(this->m_nFilesize);
			return false;
		case 2:
			dsp.Read(this->m_strFilename,dwLen);
			return false;
		case 3:						//序列化最后一个属性
			if(this->m_ofs.is_open()==FALSE)
			{
				this->m_hFileDetail.strPathname	=this->m_strFilename.c_str();
				this->m_hFileDetail.nFilesize	=this->m_nFilesize;
				this->m_hFileDetail.nCurrLen	=FILE_SECT_SIZE;

				//传送文件名和尺寸,并且打开文件输出流,准备写
				::SendMessage(this->m_hFileDetail.hwnd,MSG_SETFILENAMESIZE,
										(WPARAM)&this->m_hFileDetail,0);

				//打开对话框,选择被保存的文件名
				CFileDialog fileDialog(FALSE,NULL,this->m_strFilename.c_str(),OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT);
				if(fileDialog.DoModal()==IDOK)
				{
					//得到被选择的文件名
					this->m_hFileDetail.strPathname	=fileDialog.GetPathName();
					//重新传送文件名和尺寸
					::SendMessage(this->m_hFileDetail.hwnd,MSG_SETFILENAMESIZE,
										(WPARAM)&this->m_hFileDetail,0);

					this->m_hFileDetail.nCurrLen	=0;

					if(DSP::OpenOfstreamForWrite(this->m_ofs,this->m_hFileDetail.strPathname)==FALSE)
					{
						//如果找开文件失败
						dsp.Read(NULL,0);
						return true;
					}
				}
				else
				{
					dsp.Read(NULL,0);
					return true;
				}
			}
			else
			{
				//文件已经写完
				this->m_ofs.flush();
				this->m_ofs.close();
			}
			dsp.Read(this->m_buff,dwLen);
	}

	return true;
}

bool DSPFile::AttrSectRecv(BYTE byClassLevels,BYTE byAttrNo,const char* const lpBuff,DWORD dwLen,bool bLast)
{
	this->m_ofs.write(lpBuff,dwLen);
	this->m_hFileDetail.nCurrLen	+=dwLen;
	::SendMessage(this->m_hFileDetail.hwnd,MSG_RECVSECT,(WPARAM)&this->m_hFileDetail,dwLen);
	return true;
}

bool DSPFile::AttrSectSend(BYTE byClassLevels,BYTE byAttrNo,char** const lpBuff,DWORD& dwLen,bool& bContinue)
{
	this->m_ifs.read(*lpBuff,dwLen);
	if(this->m_ifs.eof())
	{
		//如果文件已经结束
		//得到文件的大小
		int size	=this->m_ifs.tellg();

		//得到最后读取的文件尺寸,设定最后接收的字节数
		dwLen		=size%dwLen;

		//设定不需要再继续接收
		bContinue	=false;
	}
	this->m_hFileDetail.nCurrLen	+=dwLen;
	::SendMessage(this->m_hFileDetail.hwnd,MSG_SENDSECT,(WPARAM)&this->m_hFileDetail,dwLen);
	return true;
}

bool DSPFile::ReadySendFile(bool& bRun,SOCKET sock,bool bCrc,DSP::_DSPPACKET& packet,HWND hWnd) 
{
	// TODO: Add your control notification handler code here
	//开始传送文件线程
	CFileDialog fileDialog(TRUE,NULL,NULL,OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT|OFN_FILEMUSTEXIST);
	if(fileDialog.DoModal()==IDOK)
	{
		//得到被选择的包含路径的文件名
		this->m_hFileDetail.strPathname	=fileDialog.GetPathName();

		//得到被选择的文件名
		this->m_strFilename				=fileDialog.GetFileName();

		//得到文件的大小
		HANDLE	fileHandle	=::CreateFile(this->m_hFileDetail.strPathname,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,0,NULL);
		this->m_nFilesize	=::GetFileSize(fileHandle,NULL);
		::CloseHandle(fileHandle);

		//保存文件尺寸到结构中
		this->m_hFileDetail.nFilesize	=this->m_nFilesize;

		//初始化传送文件的步长
		this->m_hFileDetail.nCurrLen	=FILE_SECT_SIZE;

		//初始化值
		this->m_hFileDetail.hwnd		=hWnd;
		this->m_hFileDetail.lpbRun		=&bRun;
		bRun							=true;

		//通知准备传送的文件名和尺寸
		::SendMessage(this->m_hFileDetail.hwnd,MSG_SETFILENAMESIZE,(WPARAM)&this->m_hFileDetail,0);

		//初始化传送文件的尺寸
		this->m_hFileDetail.nCurrLen	=0;

		//设置等待时间为10分钟
		packet.Timeout.tv_sec			=600;
		packet.SetParameter(FALSE,bCrc);

		//序列化对象
		if(packet.WriteObject(sock,*this))
		{
			//传送完成
			::SendMessage(this->m_hFileDetail.hwnd,MSG_SENDCOMPLETE,(WPARAM)&this->m_hFileDetail,SEND_SUCCESSFUL);
			return true;
		}
		else
		{
			if(bRun)
			{
				//传送失败,可能是对方放弃或传送失败或超时
				DSP::_DSPERROR* lphErr	=packet.GetLastError();

				::SendMessage(this->m_hFileDetail.hwnd,MSG_SENDCOMPLETE,(WPARAM)&this->m_hFileDetail,
					(lphErr->nErrorNo==DSP::ERR_SEND_HEADER)?SEND_TIMEOUT:SEND_FAIL);
			}
			else
			{
				//如果是点击了放弃按钮
				::SendMessage(this->m_hFileDetail.hwnd,MSG_SENDCOMPLETE,(WPARAM)&this->m_hFileDetail,SEND_ABORT);
			}
		}
	}
	return false;
}

bool DSPFile::ReadyRecvFile(bool& bRun,SOCKET sock,DSP::_DSPPACKET& packet,HWND hWnd)
{
	//设置放充的布尔变量,改变该变量的值,可以立即中止传送,初始化为允许接收
	bRun						=true;
	this->m_hFileDetail.lpbRun	=&bRun;

	//设置进行消息传递的窗体的句柄
	this->m_hFileDetail.hwnd	=hWnd;
	
	while(true)
	{
		if(packet.ReadObject(sock,this))
		{
			//接收完成
			::SendMessage(this->m_hFileDetail.hwnd,MSG_SENDCOMPLETE,(WPARAM)&this->m_hFileDetail,RECV_SUCCESSFUL);
		}
		else
		{
			if(bRun)
			{
				//接收失败,可能是对方放弃或接收数据时失败或超时
				DSP::_DSPERROR* lphErr	=packet.GetLastError();

				::SendMessage(this->m_hFileDetail.hwnd,MSG_SENDCOMPLETE,(WPARAM)&this->m_hFileDetail,
					(lphErr->nErrorNo==DSP::ERR_RECV_HEADER)?RECV_TIMEOUT:RECV_FAIL);
			}
			else
			{
				//如果是接收被放弃
				::SendMessage(this->m_hFileDetail.hwnd,MSG_SENDCOMPLETE,(WPARAM)&this->m_hFileDetail,RECV_ABORT);
			}
			return false;
		}
	}
}

bool DSPFile::GetCompleteInfo(int which, CString &str)
{
	switch(which)
	{
		case SEND_SUCCESSFUL:
			str	="传送文件成功!";
			return true;
		case RECV_SUCCESSFUL:
			str	="接收文件成功!";
			return true;
		case SEND_TIMEOUT:
			str	="传送文件超时或对方关闭了连接!";
			break;
		case RECV_TIMEOUT:
			str	="接收文件超时或对方关闭了连接!";
			break;
		case SEND_FAIL:
			str	="传送文件失败,可能是连接被中断或超时!";
			break;
		case RECV_FAIL:
			str	="接收文件失败,可能是连接被中断或超时,或接收到了不正确的信息!";
			break;
		case SEND_ABORT:
			str	="传送文件过程被中止!";
			break;
		case RECV_ABORT:
			str	="接收文件过程被中止!";
			break;
	}
	return false;
}

⌨️ 快捷键说明

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