加入多线程的文件下载程序

来源:互联网 发布:软件开发质量保证措施 编辑:程序博客网 时间:2024/05/17 06:19
download.h
#pragma once#include "stdafx.h"#define BLen 8192using namespace std;unsigned int __stdcall Fun(void *pPM);DWORD SyncWaitForMultipleObjs(HANDLE * handles, int count);HANDLE  g_hThreadParameter;CRITICAL_SECTION g_csThreadCode;long g_nNum; //全局资源class FileInfo{public:int Num_Thread;//线程数int blockLen;//每块长度BYTE Buffer[8192];int ReadLen;int fileLen;CFile cf;//要打开的网页下载文件CHttpFile *pF;//写入文件}FN1, FN2[10240];
// 多线程下载.cpp: 定义控制台应用程序的入口点。//#include "stdafx.h"#include "Download.h"#define _CRT_SECURE_NO_WARNINGSLPWSTR MtoW(char* temp, LPTSTR buffera) {DWORD dwNum = MultiByteToWideChar(CP_ACP, 0, temp, -1, NULL, 0);//计算这个GB2312实际有几个字组成wchar_t* pwText;pwText = new wchar_t[dwNum];if (!pwText){delete[]pwText;}MultiByteToWideChar(CP_ACP, 0, temp, -1, pwText, dwNum);//把GB2312变成UNICODEwcscpy_s(buffera, MAX_PATH, pwText);delete[]pwText;return buffera;}bool InternetDownload(const CString &strURL, const CString &strFN){CInternetSession internetSession(L" ",1,PRE_CONFIG_INTERNET_ACCESS,NULL,NULL,0);BOOL bSucceed = TRUE;// 统一以二进制方式下载DWORD       dwFlag = INTERNET_FLAG_TRANSFER_BINARY | INTERNET_FLAG_DONT_CACHE | INTERNET_FLAG_RELOAD;//子类对基类进行了强制类型转换,利用函数打开要下载的网址链接 wangsl//将要下载文件的信息 FN1.pF = (CHttpFile*)internetSession.OpenURL(strURL, 1, dwFlag);// 得到文件大小CString      str;FN1.pF->QueryInfo(HTTP_QUERY_CONTENT_LENGTH, str);FN1.fileLen = _ttoi(str);//文件大小,将字符串转换成整形//int nTotalSize = nFileSize;cout << "请输入线程数:" << endl;//测试时写死FN1.Num_Thread = 64;FN1.blockLen = FN1.fileLen/FN1.Num_Thread;//每块长度cout << "文件总长度为:" << FN1.fileLen << endl;try{if (FN1.pF != NULL){////创建下载文件,不存在就创建,存在就直接写入 wangslif (!FN1.cf.Open(strFN, CFile::modeCreate | CFile::modeWrite, NULL)){return FALSE;}//添加线程锁g_hThreadParameter = CreateMutex(NULL, FALSE, NULL);InitializeCriticalSection(&g_csThreadCode);HANDLE  handle[MAX_PATH];g_nNum = 0;int i = 0;while (i < FN1.Num_Thread){handle[i] = (HANDLE)_beginthreadex(NULL, 0, Fun, &i, 0, NULL);WaitForSingleObject(g_hThreadParameter, INFINITE); //等待互斥量被触发  i++;}SyncWaitForMultipleObjs(handle, FN1.Num_Thread);//销毁互斥量和关键段  CloseHandle(g_hThreadParameter);DeleteCriticalSection(&g_csThreadCode);for (i = 0; i < FN1.Num_Thread; i++)CloseHandle(handle[i]);FN1.cf.Close();FN1.pF->Close();//system("pause");delete FN1.pF;}}catch (CInternetException& e){char szBuffer[128];ZeroMemory(szBuffer, sizeof(szBuffer));LPTSTR buffer = NULL;MtoW(szBuffer, buffer);e.GetErrorMessage(buffer, sizeof(buffer), NULL);TRACE("InternetDownload, Exception: %s ", buffer);}catch (...){TRACE("InternetDownload, Exception: ... ");}internetSession.Close();if (!bSucceed)DeleteFile(strFN);return bSucceed;}#define L 2*BLenunsigned int __stdcall Fun(void *pPM){int nThreadNum = *(int *)pPM;ReleaseMutex(g_hThreadParameter);//触发互斥量  Sleep(10);//some work should to do  EnterCriticalSection(&g_csThreadCode);printf("线程编号为%d  全局资源值为%d\t", nThreadNum, g_nNum);//写入文件开始 int ReadLen = 0;BYTE Buffer[BLen];ZeroMemory(Buffer, sizeof(Buffer));//为buffer分配空间int offset = g_nNum * FN1.blockLen;//偏移量//如果是文件最后一段if (g_nNum == FN1.Num_Thread - 1){FN1.blockLen = FN1.fileLen - g_nNum * FN1.blockLen;}int count = 0;//统计循环写入长度int i = 0;//统计循环次数int Write_Num = FN1.blockLen / BLen + 1;//写入次数int File_tail = FN1.blockLen % BLen;//文件段末尾//FN1.pF->Seek(offset,0);//查找每块写入位置FN1.cf.Seek(offset, CFile::begin);while (i < Write_Num){if (count != BLen * (Write_Num-1)){ReadLen = FN1.pF->Read(Buffer, BLen);FN1.cf.Write(Buffer, ReadLen);count += BLen;i++;}else//如果循环到最后一段 其长度不足或等于Blen 则{ReadLen = FN1.pF->Read(Buffer, File_tail);FN1.cf.Write(Buffer, ReadLen);i++;}}printf("整段长度为:%d\t", FN1.blockLen);cout << count << endl;//写入结束g_nNum++;//Sleep(0);//some work should to do  LeaveCriticalSection(&g_csThreadCode);return 0;}//解除最多等待64个线程限制DWORD SyncWaitForMultipleObjs(HANDLE * handles, int count){int waitingThreadsCount = count;int index = 0;DWORD res = 0;while (waitingThreadsCount >= MAXIMUM_WAIT_OBJECTS){res = WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, &handles[index], TRUE, INFINITE);if (res == WAIT_TIMEOUT || res == WAIT_FAILED){puts("1. Wait Failed.");return res;}waitingThreadsCount -= MAXIMUM_WAIT_OBJECTS;index += MAXIMUM_WAIT_OBJECTS;}if (waitingThreadsCount > 0){res = WaitForMultipleObjects(waitingThreadsCount, &handles[index], TRUE, INFINITE);if (res == WAIT_TIMEOUT || res == WAIT_FAILED){puts("2. Wait Failed.");}}return res;}int main(){clock_t start, finish;double totaltime;char str1[] = "http://sqdownb.onlinedown.net/down/ZWCAD2018.exe", str2[] = "1.iso";CString ip(str1), name(str2);start = clock();InternetDownload(ip, name);finish = clock();totaltime = (double)(finish - start) / CLOCKS_PER_SEC;cout << "\n此程序的运行时间为" << totaltime << "秒!" << endl;system("pause");return 0;}


原创粉丝点击