#include <stdio.h>
#include <windows.h>
#include <stdlib.h>
#include <iostream>
#define _CRT_SECURE_NO_WARNINGS
using namespace std;
CRITICAL_SECTION g_csThreadCode;
volatile long g_nNum; //全局资源
struct ThreadInfo
{
int i;
int flen; //fLen
int blocklen; //blockLen
FILE* a; //fsrc
FILE* b; //ftmp
int threadnum; //N
}Info;
DWORD WINAPI Fun(void* pPM)
{
//由于创建线程是要一定的开销的,所以新线程并不能第一时间执行到这来
//int nThreadNum = *(int *)pPM; //子线程获取参数
EnterCriticalSection(&g_csThreadCode);
//InterlockedIncrement(&g_nNum); // 全局变量
//Sleep(0);
printf("第 %d个线程正在执行!\n", g_nNum+1);
//写入文件
int offset = g_nNum*Info.blocklen; //i*blockLen; //计算偏移量
fseek(Info.a, offset, SEEK_SET);
fseek(Info.b, offset, SEEK_SET);
int count = 0; //统计写入ftmp的数量
if (g_nNum == Info.threadnum - 1)
Info.blocklen = Info.flen - Info.blocklen*(Info.threadnum - 1); //最后一块的长度
while (count<Info.blocklen && !feof(Info.a))
{
fputc(fgetc(Info.a), Info.b);
count++;
}
//写入结束
g_nNum++;
LeaveCriticalSection(&g_csThreadCode);
return 0;
}
int main()
{
g_nNum = 0;
int THREAD_NUM; //子线程个数
printf("请输入线程数:\n");
cin >> THREAD_NUM;
//打开要复制的文件
FILE *fsrc = fopen("D:\\document\\123.mp4", "rb"); // 源文件
fseek(fsrc, 0, SEEK_END);
int fLen = ftell(fsrc); // 文件长度
printf("文件长度:%d\n", fLen);
int blockLen = fLen / THREAD_NUM; // 每一块的长度
printf("blockLen:%d\n", blockLen);
//创建大小相同的文件
FILE *ftmp; // 临时文件,
char tName[20];
char tdir[60] = "D:\\document\\";
sprintf(tName, "new123.mp4");//生成文件名
strcat(tdir, tName); //产生临时目录
ftmp = fopen(tdir, "wb"); // 生成临时文件
fseek(ftmp, fLen - 1, 0);//指定大小
fputc(0, ftmp);
HANDLE handle[MAX_PATH];
InitializeCriticalSection(&g_csThreadCode);
int i = 0;
Info.a = fsrc;
Info.b = ftmp;
Info.blocklen = blockLen;
Info.flen = fLen;
Info.threadnum = THREAD_NUM;
while (i < THREAD_NUM)
{
//等子线程接收到参数时主线程可能改变了这个i的值
handle[i] = CreateThread(NULL, 0, Fun, &Info, 0, NULL);
i++;
}
//保证子线程已全部运行结束
WaitForMultipleObjects(THREAD_NUM, handle, TRUE, INFINITE);
DeleteCriticalSection(&g_csThreadCode);
system("pause");
return 0;
}
// MultipleTask.cpp: 定义控制台应用程序的入口点。
// 每个下载是单独的一个线程
#include "stdafx.h"
#include "DownloadInfo.h"
#include <sstream>
//解除最多等待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;
}
LPWSTR 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变成UNICODE
wcscpy_s(buffera, MAX_PATH, pwText);
delete[]pwText;
return buffera;
}
bool InternetDownload(const string &URL, const string &FN)
{
CString strURL, strFN;
strURL = URL.c_str();
strFN = FN.c_str();
CInternetSession internetSession(L"DownloaderWsl",
1,
PRE_CONFIG_INTERNET_ACCESS,
NULL,
NULL,
0);
BOOL bSucceed = TRUE;
try
{
// 统一以二进制方式下载
DWORD dwFlag = INTERNET_FLAG_TRANSFER_BINARY | INTERNET_FLAG_DONT_CACHE | INTERNET_FLAG_RELOAD;
//子类对基类进行了强制类型转换,利用函数打开要下载的网址链接 wangsl
//将要下载文件的信息
CHttpFile * pF = (CHttpFile*)internetSession.OpenURL(strURL, 1, dwFlag);
// 得到文件大小
CString str;
pF->QueryInfo(HTTP_QUERY_CONTENT_LENGTH, str);
int nFileSize = _ttoi(str); //文件大小,将字符串转换成整形
//int nTotalSize = nFileSize;
if (pF != NULL)
{
//创建下载文件,不存在就创建,存在就直接写入 wangsl
CFile cf;
if (!cf.Open(strFN, CFile::modeCreate | CFile::modeWrite, NULL))
{
return FALSE;
}
//
BYTE Buffer[8192];
//为Buffer分配空间 wangsl
ZeroMemory(Buffer, sizeof(Buffer));
int nReadLen = 0;
while ((nReadLen = pF->Read(Buffer, sizeof(Buffer))) > 0) //每次读取固定长度到Buffer中,返回实际读取的长度 wangsl
{
cf.Write(Buffer, nReadLen); //在创建的文件中写入读取的内容 wangsl
nFileSize -= nReadLen;
TRACE("剩余:%d\n", nFileSize);
}
cf.Close();
pF->Close();
delete 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;
}
unsigned int __stdcall Fun(void *pPM)
{
Info nThreadNum = *(Info *)pPM;
InternetDownload(nThreadNum.url, nThreadNum.filename);
return 0;
}
int main()
{
//接收网址数据
int n = 0;
cout << "请输入要下载的任务数:" << endl;
cin >> n;
cout << "请输入任务的URL:" << endl;
for (int k = 0; k < n ; k++)
{
cin >> FN1[k].url;
}
//接收完毕 创建线程
HANDLE handle[MAX_PATH];
int i = 0;
while (i < n)
{
int nNum = GetTickCount();
char szFilePath[MAX_PATH] = { 0 };
sprintf(szFilePath, "%d%s", nNum, FILE_TYPE);
FN1[i].filename = szFilePath;
handle[i] = (HANDLE)_beginthreadex(NULL, 0, Fun, &FN1[i], 0, NULL);
Sleep(5);
i++;
}
SyncWaitForMultipleObjs(handle, n);
for (i = 0; i < n; i++)
CloseHandle(handle[i]);
system("pause");
return 0;
}