单线程支持断点续传文件下载

单线程支持断点续传文件下载_第1张图片



MyWindow.h

#ifndef MYWINDOW_HEAD
#define MYWINDOW_HEAD
#pragma once

#include 
#include 
#include 
#include 
#include 
#pragma comment(lib ,"Wininet.lib")



class CMyApp:public CWinApp
{
public:
	//构造函数
	CMyApp();
	//析构函数
	virtual ~CMyApp();

	//重载函数
public:
	//初始函数
	virtual BOOL InitInstance();
};



class CMyWindow : public CFrameWndEx
{
public:
	CButton									m_btStart;						//开始按钮
	CButton									m_btStop;						//停止按钮
	CStatic									m_stProcess;					//百分进度
	CEdit										m_editUrl;						//下载地址
	CProgressCtrl						m_ProcessPb;				//下载进度条
	HANDLE									m_Thread;						//线程句柄
	BOOL										m_IsStop;						//是否停止

public:
	//构造函数
	CMyWindow();
	//析构函数
	virtual ~CMyWindow();

	//线程函数
protected:
	static DWORD WINAPI  PBThreadProc( LPVOID lpParameter );

	//虚函数
public:
	//命令响应消息
	virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam);

	//消息映射
public:
	afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
	DECLARE_MESSAGE_MAP()
};



#endif


#include "MyWindow.h"

CMyApp myapp;

#define									 IDC_START									1001								 //开始按钮
#define									 IDC_STOP										1002								//暂停按钮
#define									 IDC_PROCESS								1003								//进度状态


//构造函数
CMyApp::CMyApp()
{

}

//析构函数
CMyApp::~CMyApp()
{

}

//初始函数
BOOL CMyApp::InitInstance()
{
	m_pMainWnd = new CMyWindow();
	m_pMainWnd->ShowWindow(SW_SHOW);
	m_pMainWnd->UpdateWindow();
	return TRUE;
}



BEGIN_MESSAGE_MAP(CMyWindow, CFrameWndEx)
	ON_WM_CREATE()
END_MESSAGE_MAP()

//构造函数
CMyWindow::CMyWindow()
{
	Create(NULL, TEXT("My Window"));
}
//析构函数
CMyWindow::~CMyWindow()
{
}

//命令响应消息
BOOL CMyWindow::OnCommand( WPARAM wParam, LPARAM lParam )
{
	int wmId=LOWORD(wParam);
	switch (wmId)
	{
	case IDC_START:
		{								
			//创建线程
			m_IsStop=FALSE;
			m_Thread=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)PBThreadProc,this,0,0);
			CloseHandle(m_Thread);
			return true;
		}
		break;
	case IDC_STOP:
		{
			m_IsStop=TRUE;
			return true;
		}
		break;
	default:
		return true;
	}

	return __super::OnCommand(wParam,lParam);

}

//创建事件
int CMyWindow::OnCreate( LPCREATESTRUCT lpCreateStruct )
{
	__super::OnCreate(lpCreateStruct);

	//居中窗口
	SetWindowPos(NULL,0,0,600,400,SWP_SHOWWINDOW);
	SetActiveWindow();
	SetForegroundWindow();
	CenterWindow(GetParent());


	//创建按钮
	RECT rect={0,0,0,0};
	m_btStart.Create(TEXT("开始"),WS_CHILD|WS_VISIBLE,rect,this,IDC_START);
	m_btStop.Create(TEXT("停止"),WS_CHILD|WS_VISIBLE,rect,this,IDC_STOP);
	m_stProcess.Create(TEXT("0 %"),WS_CHILD|WS_VISIBLE|BS_DEFPUSHBUTTON,rect,this,IDC_PROCESS);
	m_editUrl.Create(WS_CHILD|WS_VISIBLE|WS_BORDER,rect,this,NULL);
	m_ProcessPb.Create(WS_CHILD | WS_VISIBLE,rect,this,NULL);

   m_btStart.SetWindowPos(NULL,0,0,60,30,SWP_SHOWWINDOW);
   m_btStop.SetWindowPos(NULL,100,0,60,30,SWP_SHOWWINDOW);
   m_stProcess.SetWindowPos(NULL,0,100,100,30,SWP_SHOWWINDOW);
   m_editUrl.SetWindowPos(NULL,0,50,450,30,SWP_SHOWWINDOW);
   m_ProcessPb.SetWindowPos(NULL,0,150,450,30,SWP_SHOWWINDOW);

	m_editUrl.SetWindowText(_T("http://dldir1.qq.com/music/clntupate/QQMusicForYQQ.exe") );


	m_IsStop=FALSE;
	m_Thread=NULL;
	return true;
}


DWORD WINAPI  CMyWindow::PBThreadProc( LPVOID lpParameter )
{

	//定义变量
	CMyWindow* pMyWindow = (CMyWindow *)lpParameter;
	assert(pMyWindow);if (pMyWindow==NULL)return FALSE;


	LONGLONG dwByteToRead=0;
	DWORD dwSizeOfRq=4;
	DWORD dwBytes=0;
	LONGLONG sum=0;
	DWORD dwSize=0;
	PBRANGE range={0};                        //进度条的范围
	void * szTemp[16384]={0};			 //接收数据
	HINTERNET hConnect=NULL;
	FILE *pfDownLoad=NULL;				//下载文件
	TCHAR  szUrlAdd[MAX_PATH]={0}; 
	TCHAR szHead[128]= _T("Accept: */*\r\n\r\n");
	TCHAR pBuf[MAX_PATH]={0};         //存放路径的变量

	//本地系统的连接状态
	DWORD dwFlags;
	if(InternetGetConnectedState(&dwFlags,0)==FALSE)
	{
		::MessageBox(NULL,_T("没有网络连接!"),_T("提示"),MB_OK);
		return 0;
	}

	//初始化应用程序使用的WinInet函数
	TCHAR strAgent[64];
	swprintf(strAgent,_T("Agent%ld"),timeGetTime());
	HINTERNET hopen;
	if(!(dwFlags&INTERNET_CONNECTION_PROXY))
		hopen=InternetOpen(strAgent,INTERNET_OPEN_TYPE_PRECONFIG_WITH_NO_AUTOPROXY,NULL,NULL,0);
	else
		hopen=InternetOpen(strAgent,INTERNET_OPEN_TYPE_PRECONFIG,NULL,NULL,0);

	if(!hopen)
	{
		::MessageBox(NULL,_T("打不开网络连接!"),_T("提示"),MB_OK);
		return 0;
	}


	pMyWindow->m_editUrl.GetWindowText( szUrlAdd , ARRAYSIZE(szUrlAdd) );
    GetCurrentDirectory(MAX_PATH,pBuf);    
	wcscat(pBuf, wcsrchr( szUrlAdd ,'/') );

	long fileSize=0;
	pfDownLoad=_wfopen( pBuf ,_T("r"));
	if (pfDownLoad)
	{
		fseek(pfDownLoad, 0, SEEK_END);
		fileSize = ftell(pfDownLoad);
		_stprintf(szHead, _T("Range: bytes=%d-\r\nAccept: */*\r\n\r\n"), fileSize);
		fclose(pfDownLoad);

		pfDownLoad=_wfopen( pBuf ,_T("rb+ "));
		if(pfDownLoad==NULL)
		{
			::MessageBox(NULL,_T("打开本地文件失败!"),_T("提示"),MB_OK);
			return 0;
		}
		fseek(pfDownLoad, 0, SEEK_END);
	}
	else
	{
		pfDownLoad=_wfopen( pBuf ,_T("wb+"));
		_stprintf(szHead, _T("Accept: */*\r\n\r\n"));
		if(pfDownLoad==NULL)
		{
			::MessageBox(NULL,_T("打开本地文件失败!"),_T("提示"),MB_OK);
			return 0;
		}
	}


	


	//查询有关HTTP请求的信息  
	if(!(hConnect=InternetOpenUrl(hopen,szUrlAdd,szHead,wcslen(szHead),INTERNET_FLAG_DONT_CACHE|INTERNET_FLAG_PRAGMA_NOCACHE,0)))
	{
		::MessageBox(NULL,_T("打开网络地址失败!"),_T("提示"),MB_OK);
		return 0;
	}

	//查询是否支持断点续传
	//Accept-Ranges: bytes
	if(HttpQueryInfo(hConnect,HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_NUMBER ,(LPVOID)&dwByteToRead,&dwSizeOfRq,NULL)==FALSE)
	{
		return false;
	}
	if (dwByteToRead==206)
	{
		OutputDebugString(TEXT("支持断点续传"));
	}



	//获取文件大小
	if(HttpQueryInfo(hConnect,HTTP_QUERY_CONTENT_LENGTH|HTTP_QUERY_FLAG_NUMBER,(LPVOID)&dwByteToRead,&dwSizeOfRq,NULL)==FALSE)
	{
		dwByteToRead=0;
	}



	//设置进度条的范围
	pMyWindow->m_ProcessPb.SendMessage(PBM_SETRANGE, (WPARAM)0, (LPARAM)(MAKELPARAM(0,100)) );
	//获取进度条的范围     //TRUE 表示返回值为范围的最小值,FALSE表示返回最大值
	pMyWindow->m_ProcessPb.SendMessage( PBM_GETRANGE, (WPARAM)TRUE,(LPARAM)&range );


	// 
	TCHAR sumdata[64]={0};
	
	while(TRUE)
	{
		
		//2016年5月16日14:42:07
		//下载超过255MB大的文件下载就停止了。不知道什么原因
		//读取数据
		if(InternetReadFile(hConnect,szTemp,16384,&dwSize)==FALSE)	//16384
		{
			InternetCloseHandle(hopen);
			fclose(pfDownLoad);
			::MessageBox(NULL,_T("网络中断!"),_T("提示"),MB_OK);
			return 0;
		}
		if(dwSize==0)break;

		sum+=dwSize;
		fwrite(szTemp,dwSize,1,pfDownLoad);
		swprintf(sumdata,_T("%d %%"),(sum*100)/dwByteToRead);
			
		//设置进度条当前值
		pMyWindow->m_ProcessPb.SendMessage(PBM_SETPOS, (WPARAM)(sum*100)/dwByteToRead, (LPARAM)0 );
		pMyWindow->m_stProcess.SetWindowText(sumdata);

		//停止判断
		if (pMyWindow->m_IsStop==TRUE)break;
	}

	//关闭一个Internet手柄
	InternetCloseHandle(hopen);
	fclose(pfDownLoad);

	//pthis->m_ProcessPb.SendMessage(PBM_SETPOS, (WPARAM)range.iLow, (LPARAM)0 ); //将进度条复位
	//pthis->m_ProcessPb.ShowWindow(SW_HIDE );		//隐藏进度条
	//pthis->m_stProcess.ShowWindow(SW_HIDE );  //隐藏 百分比控件

	//::MessageBox(NULL,TEXT("文件下载完毕"),NULL,MB_OK);
	return 0;
}


你可能感兴趣的:(网络编程)