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

📄 downloadconn.cpp

📁 wisock应用队列思想实现单线程多任务http下载的类. 实现多文件同时下载,断点续传,流量统计等.
💻 CPP
字号:
#include ".\downloadconn.h"
#include "struct.h"
#include <process.h>    /* _beginthread, _endthread */

CDownloadConn::CDownloadConn(LPTSTR lpHost,UINT port)
{
	m_lpHost = lpHost;
	m_port = port;
	m_netFlow = CNetFlowRecoder::GetInstance();
}

CDownloadConn::~CDownloadConn(void)
{
}

/*========================================================================
	增加 一个下载文件任务
	lpszDownloadUrl	远程url		如: /file/
	localSavePath	本地路径	如: c://download/
	lpszFileName	文件名		如: index.html

	调用AddTask,由AddTask负责断点续传
========================================================================*/
bool CDownloadConn::AddDownloadFile(LPCTSTR lpszDownloadUrl,LPCTSTR localSavePath,LPTSTR lpszFileName)
{
	return AddTask( m_lpHost,m_port, lpszDownloadUrl,localSavePath,lpszFileName);//内部控制断点续传
}
/*========================================================================
	开始整个任务的下载
========================================================================*/
void CDownloadConn::StartTask()
{
	_beginthread( Run,0,(void*)this);//文件下载
	_beginthread( RefreshSpeed,0,(void*)m_netFlow);//实时流量统计

}
/*========================================================================
	得到下载速率
========================================================================*/
int CDownloadConn::GetRate()
{
	return m_netFlow->GetCurSpeed();

}
/*========================================================================
	得到下载百分比
========================================================================*/
float CDownloadConn::GetPercentage()
{
	return m_netFlow->GetCurPersentage();
}
/*========================================================================
	线程函数
	更新下载速率
========================================================================*/
void CDownloadConn::RefreshSpeed(void* lParam)
{
	CNetFlowRecoder *netFlow = (CNetFlowRecoder*)lParam;
	
	while( !netFlow->m_isBegin)//下载还未开始,等待
	{
		Sleep(1);
		printf("waitting\n");
	}
	while( !netFlow->IsCompleted() )//下载还结束,更新速率
	{
		netFlow->RefreshSpeed();
	}
	netFlow->m_iNetRate = 0;//下载结束,速率置0
}


/*========================================================================
	把tssklist的任务请求发送到content server
========================================================================*/
void CDownloadConn::SendTaskRequest(list<DOWNLOADLIST*> *taskList)
{
	list<DOWNLOADLIST*>::iterator taskIterator;
	for(taskIterator = taskList->begin();taskIterator != taskList->end();++taskIterator)
	{

		CDownloadSocket *lpDownloadSocket= (*taskIterator)->downloadSocket;
		CDownloadFile *lpDownloadFile = (*taskIterator)->downloadFile;

		lpDownloadSocket->Connect(m_lpHost,m_port);
		lpDownloadSocket->Login();
		lpDownloadSocket->SendRequest(lpDownloadFile->m_lpszFileName,lpDownloadFile->m_iCurOffset);
	}

}

/*========================================================================
	文件下载线程函数(太长了,不怎么好^_^)
========================================================================*/
void CDownloadConn::Run(void* lParam)
{
	CDownloadConn *lpThis = (CDownloadConn*)lParam;
	list<DOWNLOADLIST*>::iterator taskIterator;
	list<DOWNLOADLIST*> *taskList;
	taskList = &(lpThis->m_taskList);
	lpThis->SendTaskRequest(taskList);//发送请求

	TCHAR recvBuf[RECV_BUF_SIZE];
	int recvSize;
	//接收文件	
	while(! taskList->empty() )
	{
		for(taskIterator = taskList->begin();taskIterator != taskList->end();++taskIterator)
		{
			CDownloadSocket *lpDownloadSocket= (*taskIterator)->downloadSocket;
			CDownloadFile *lpDownloadFile = (*taskIterator)->downloadFile;
			CInfoFile *lpInfoFile = (*taskIterator)->infoFile;

			recvSize = lpDownloadSocket->RecvData(recvBuf);

			if(( DOWNLOAD_ESTABLISHED == (*taskIterator)->state )||( DONWLOAD_RESUME == (*taskIterator)->state) )//刚完成建立http连接,则分析ip 头
			{
				RESPONSECODE response;
				response = lpDownloadSocket->GetResponse(recvBuf);//得到返回状态
				switch(response)
				{
				case CODE_ERROR:
					{
						//注意,没有对外通知下载失败//winfree
						lpThis->RemoveTask(taskIterator);
						list<DOWNLOADLIST*>::iterator tempIterator;
						tempIterator = taskIterator;

						taskList->erase(taskIterator);
						
						++tempIterator;
						//如果没有到链尾 
						if(tempIterator != taskList->end() )
						{
							taskIterator = tempIterator;
						}

					};
					break;
				case CODE_OK:
					{
						//对第一个包进行分析,处理
						UINT iContentLen = 0;
						iContentLen = lpDownloadSocket->GetContentLen(recvBuf);//得到下载文件长度
						if( DONWLOAD_RESUME == (*taskIterator)->state)//如果是断点续传,则从记录文件的信息初始化
						{							
							
							lpThis->m_netFlow->RefreshFlow(lpDownloadFile->m_iCurOffset );//把之前下载的长度加到flow中
							lpThis->m_netFlow->AddTotalFlow(lpDownloadFile->m_iContentLen);//把文件长度累加到网络流量统计的下载总长度记录中
						}
						else
						{
							lpThis->m_netFlow->AddTotalFlow(iContentLen);//把文件长度累加到网络流量统计的下载总长度记录中
						}
						recvSize -= lpDownloadSocket->GetHeaderLen(recvBuf);//第一个包的长度要减去http头长度				
						lpDownloadSocket->IgnoreIpHeader(recvBuf);//删去http头
						lpDownloadFile->SetContentLen(iContentLen);//设置文件长度
						(*taskIterator)->state = DOWNLOAD_CONTINUE;//置为已处理s
					};
					break;
				}	
			}			
			if((recvSize!= 0)&&(recvSize!= SOCKET_ERROR ))
			{
				lpThis->m_netFlow->RefreshFlow(recvSize);//流量增加s
				lpDownloadFile->SaveFile(recvBuf,recvSize);//把下载的数据写到文件s
				lpInfoFile->WriteProcessInfo(lpDownloadFile);
				
				//Sleep(50);
		//		printf("%d\n",lpThis->m_netFlow->GetCompletedFlow());
			}
			else
			{				
				printf("aaaaaaaaaaaaaaaaaa\n");
				lpThis->RemoveTask(taskIterator);
				taskList->erase(taskIterator);
				
				break;//直接退出for循环,从第一个任务重新开始,为了写代码方便
			}
		}
	}
}

⌨️ 快捷键说明

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