织梦CMS - 轻松建站从此开始!

罗索

当前位置: 主页>杂项技术>VC(MFC)>

多线程下载

jackyhwei 发布于 2011-08-08 09:18 点击:次 
多线程实现HTTP/FTP文件下载的源码
TAG:

CInternetDownload.h

    #pragma once 
     
    class CDownloadDlg; 
    class CInternetDownload 
    { 
    public: 
        typedef struct 
        { 
            DWORD nStart;//文件片段的起始位置 
            DWORD nEnd;//文件片段的长度 
            size_t nIndex;//当前线程的编号 
            size_t nTotal; 
            CInternetDownload* pThis; 
        } ThreadParam; 
     
        CInternetDownload(CDownloadDlg* pDlg); 
        virtual ~CInternetDownload(void); 
     
        virtual int Download(const CString& strUrl, size_t nThreads); 
     
    protected: 
        static CString s_strUrl; 
        static CDownloadDlg* s_pDlg; 
     
        virtual DWORD GetFileLength(const CString& strUrl) = 0; 
        virtual CFile* GetInternetFile(LPVOID) = 0; 
        static UINT ServerWorkerThread(LPVOID lpParam); 
     
        CInternetSession internetSession; 
     
    private: 
        CFile* m_internetFile; 
    }; 

InternetDownload.cpp

    #include "StdAfx.h" 
    #include "./internetdownload.h" 
    #include "DownloadDlg.h" 
     
    CDownloadDlg* CInternetDownload::s_pDlg = NULL; 
    CString CInternetDownload::s_strUrl; 
     
    CInternetDownload::CInternetDownload(CDownloadDlg* pDlg) 
    : m_internetFile(NULL) 
    { 
        s_pDlg = pDlg; 
    } 
     
    CInternetDownload::~CInternetDownload(void) 
    { 
    } 
     
    UINT CInternetDownload::ServerWorkerThread(LPVOID lpParam) 
    { 
        ThreadParam *pParam = static_cast<ThreadParam *>(lpParam); 
     
        CFile *pFile = pParam->pThis->GetInternetFile(lpParam); 
     
        if (!pFile) 
            return -1; 
     
        CFile localFile; 
        CString strFileName; 
        strFileName.Format("c://temp.part%d", pParam->nIndex); 
        if (!localFile.Open(strFileName, CFile::modeCreate | CFile::modeWrite)) 
            return -1; 
     
        char * const pBuffer = new char[1024]; 
     
        DWORD nLeft = pParam->nEnd - pParam->nStart + 1; 
        while (TRUE) 
        { 
            int nRead = pFile->Read(pBuffer, nLeft > 1024 ? 1024 : nLeft); 
            localFile.Write(pBuffer, nRead); 
     
            if (nRead < 1024) 
                break; 
     
            nLeft -= nRead; 
        } 
     
        localFile.Close(); 
     
        delete []pBuffer; 
     
        pFile->Close(); 
        delete pFile; 
     
        s_pDlg->PostMessage(WM_DOWNLOADED_MESSAGE, pParam->nTotal, pParam->nIndex); 
     
        delete pParam; 
        pParam = NULL; 
     
        return 0; 
    } 

    int CInternetDownload::Download(const CString& strUrl, size_t nThreads) 
    { 
        s_strUrl = strUrl; 
        DWORD nFileSize = GetFileLength(strUrl); 
     
        UINT nSegmentLength =  (nFileSize + nThreads - 1) / nThreads; 
     
        for (size_t i = 0; i < nThreads; i++) 
        { 
            ThreadParam *lpParam = new ThreadParam; 
            //memset(lpParam, '/0', sizeof(ThreadParam)); 
            lpParam->nTotal = nThreads; 
            lpParam->nIndex = i; 
            lpParam->nStart = nSegmentLength * i; 
            lpParam->nEnd = lpParam->nStart + nSegmentLength - 1; 
            lpParam->pThis = this; 
            if (lpParam->nEnd >= nFileSize) 
                lpParam->nEnd = nFileSize - 1; 
     
            AfxBeginThread(ServerWorkerThread, static_cast<LPVOID>(lpParam), THREAD_PRIORITY_NORMAL, 0, 0, NULL); 
            //CreateThread(NULL, 0, ServerWorkerThread, (LPVOID)i, 0, 0); 
        } 

        return 0; 
    } 

FtpDownload.h
    #pragma once 
    #include "InternetDownload.h" 
     
    class CFtpDownload : public CInternetDownload 
    { 
    public: 
        CFtpDownload(CDownloadDlg* pDlg); 
        virtual ~CFtpDownload(void); 
     
    //  int Download(const CString& strUrl, size_t nThreads); 
     
    private: 
     
        DWORD GetFileLength(const CString& strUrl); 
        CFile* GetInternetFile(LPVOID lpParam); 
    }; 
FtpDownload.cpp
    #include "StdAfx.h" 
    #include "./ftpdownload.h" 
     
    #include "DownloadDlg.h" 
    #include <winsock2.h> 
     
    #include "shlwapi.h" 
    #pragma comment(lib, "Wininet.lib") 
    #pragma comment(lib, "shlwapi.lib") 
     
     
    CFtpDownload::CFtpDownload(CDownloadDlg* pDlg) 
    : CInternetDownload(pDlg) 
    { 
    //  s_pDlg = pDlg; 
    } 
     
    CFtpDownload::~CFtpDownload(void) 
    { 
    } 
     
    CFile* CFtpDownload::GetInternetFile(LPVOID lpParam) 
    { 
        ThreadParam *pParam = static_cast<ThreadParam *>(lpParam); 
     
        CFtpConnection *pFtpConn = NULL; 
     
        CString strServerName, strObject, strUserName, strPassword; 
        DWORD dwServiceType; 
        INTERNET_PORT nPort; 
     
        if (!AfxParseURLEx(s_strUrl, dwServiceType, strServerName, strObject, nPort, strUserName, strPassword) || dwServiceType != INTERNET_SERVICE_FTP) 
        { 
            TRACE(_T("Not a ftp Quest! /n")); 
        } 
     
        pFtpConn = internetSession.GetFtpConnection(strServerName, strUserName, strPassword); 
     
        CString strFtpCommand; 
        strFtpCommand.Format("REST %d", pParam->nStart); 
        if (!FtpCommand(*pFtpConn, FALSE, FTP_TRANSFER_TYPE_ASCII, strFtpCommand, 0, 0)) 
        { 
            int i = WSAGetLastError(); 
            return NULL; 
        } 
     
        CFile *pFile = pFtpConn->OpenFile(strObject); 
     
        return pFile; 
    } 
    /*
    int CFtpDownload::Download(const CString& strUrl, size_t nThreads)
    {
        DWORD nFileSize = GetFileLength(strUrl);
    
        s_strUrl = strUrl;
    
        UINT nSegmentLength =  (nFileSize + nThreads - 1) / nThreads;
    
        for (size_t i = 0; i < nThreads; i++)
        {
            ThreadParam *lpParam = new ThreadParam;
            //memset(lpParam, '/0', sizeof(ThreadParam));
            lpParam->nTotal = nThreads;
            lpParam->nIndex = i;
            lpParam->nStart = nSegmentLength * i;
            lpParam->nEnd = lpParam->nStart + nSegmentLength - 1;
            lpParam->pThis = this;
            if (lpParam->nEnd >= nFileSize)
                lpParam->nEnd = nFileSize - 1;
    
            AfxBeginThread(ServerWorkerThread, static_cast<LPVOID>(lpParam), THREAD_PRIORITY_NORMAL, 0, 0, NULL);
            //CreateThread(NULL, 0, ServerWorkerThread, (LPVOID)i, 0, 0);
        }
    
        return 0;
    }
    */ 
     
    DWORD CFtpDownload::GetFileLength(const CString& strUrl) 
    { 
        CInternetSession internetSession; 
     
        CFtpConnection *pFtpConn = NULL; 
     
        CString strServerName, strObject, strUserName, strPassword; 
        DWORD dwServiceType; 
        INTERNET_PORT nPort; 
     
        if (!AfxParseURLEx(strUrl, dwServiceType, strServerName, strObject, nPort, strUserName, strPassword) || dwServiceType != INTERNET_SERVICE_FTP) 
        { 
            TRACE(_T("Not a ftp Quest! /n")); 
            return -1; 
        } 
     
        pFtpConn = internetSession.GetFtpConnection(strServerName, strUserName, strPassword); 
        //FtpCommand("REST 1024"); 
    /*  if (!FtpCommand(*pFtpConn, FALSE, FTP_TRANSFER_TYPE_ASCII, "REST 1024", 0, 0))
            return -1;*/ 
        CInternetFile *pFile = pFtpConn->OpenFile(strObject); 
     
        DWORD nFileSize = FtpGetFileSize(*pFile, 0); 
        pFile->Close(); 
        delete pFile; 
     
        return nFileSize; 
    } 
HttpDownload.h
    #pragma once 
    #include "InternetDownload.h" 
     
    class CHttpDownload : public CInternetDownload 
    { 
    public: 
        CHttpDownload(CDownloadDlg* pDlg); 
        virtual ~CHttpDownload(void); 
     
    private: 
    //  static UINT ServerWorkerThread(LPVOID lpParam); 
        DWORD GetFileLength(const CString& strUrl); 
     
        CFile* GetInternetFile(LPVOID lpParam); 
     
    public: 
    //  int Download(const CString& strUrl, int nThreads); 
        int FormatRequestHeader(void); 
    }; 
HttpDownload.cpp
    #include "StdAfx.h" 
    #include "./httpdownload.h" 
     
    #include "DownloadDlg.h" 
     
    static const char szHeaders[] = "Accept: */*/r/nUser-Agent:  Mozilla/4.0 (compatible; MSIE 5.00; Windows 98)/r/n"; 
     
    CFile* CHttpDownload::GetInternetFile(LPVOID lpParam) 
    { 
        ThreadParam *pParam = static_cast<ThreadParam *>(lpParam); 
        DWORD dwFlag = INTERNET_FLAG_TRANSFER_BINARY | INTERNET_FLAG_DONT_CACHE | INTERNET_FLAG_RELOAD; 
         
        CString strHeader;//请求头 
        strHeader.Format("%sRange: bytes=%d-%d/r/n", szHeaders, pParam->nStart, pParam->nEnd);//pParam->nIndex * 8192);//, 1024 * 1024); 
     
        return internetSession.OpenURL(s_strUrl, 1, dwFlag, strHeader, -1); 
    } 
    /* 
    UINT CHttpDownload::ServerWorkerThread(LPVOID lpParam) 
    { 
        //size_t nIndex = reinterpret_cast<size_t>(lpParam);//第几个文件片段 
        ThreadParam *pParam = static_cast<ThreadParam *>(lpParam); 
     
        char * const pBuffer = new char[1024]; 
     
        //for (int i = 0; ; i++) 
        while (TRUE) 
        { 
            int nRead = pHttpFile->Read(pBuffer, 1024); 
     
            localFile.Write(pBuffer, nRead); 
     
            if (nRead < 1024) 
                break; 
        } 
     
        localFile.Close(); 
     
        delete []pBuffer; 
     
        pHttpFile->Close(); 
        delete pHttpFile; 
     
        s_pDlg->PostMessage(WM_DOWNLOADED_MESSAGE, pParam->nTotal, pParam->nIndex); 
     
        delete pParam; 
     
        return 0; 
    } 
    */ 
     
    CHttpDownload::CHttpDownload(CDownloadDlg* pDlg) 
    : CInternetDownload(pDlg) 
    //: m_strHeader("Accept: */*/r/nUser-Agent:  Mozilla/4.0 (compatible; MSIE 5.00; Windows XP)/r/n") 
    { 
    } 
     
    CHttpDownload::~CHttpDownload(void) 
    { 
    } 
     
    /* 
    int CHttpDownload::Download(const CString& strUrl, int nThreads) 
    { 
        s_strUrl = strUrl; 
        DWORD nFileSize = GetFileLength(strUrl); 
     
        UINT nSegmentLength =  (nFileSize + nThreads - 1) / nThreads; 
     
        for (size_t i = 0; i < nThreads; i++) 
        {
            ThreadParam *lpParam = new ThreadParam; 
            //memset(lpParam, '/0', sizeof(ThreadParam)); 
            lpParam->nTotal = nThreads; 
            lpParam->nIndex = i; 
            lpParam->nStart = nSegmentLength * i; 
            lpParam->nEnd = lpParam->nStart + nSegmentLength - 1; 
            if (lpParam->nEnd >= nFileSize) 
                lpParam->nEnd = nFileSize - 1; 
     
            AfxBeginThread(ServerWorkerThread, static_cast<LPVOID>(lpParam), THREAD_PRIORITY_NORMAL, 0, 0, NULL); 
            //CreateThread(NULL, 0, ServerWorkerThread, (LPVOID)i, 0, 0); 
        } 
     
        return 0; 
    } 
    */  (shuizhiyun)

本站文章除注明转载外,均为本站原创或编译欢迎任何形式的转载,但请务必注明出处,尊重他人劳动,同学习共成长。转载请注明:文章转载自:罗索实验室 [http://www.rosoo.net/a/201108/14809.html]
本文出处:blog.csdn.net/shuizhiyun 作者:shuizhiyun
顶一下
(0)
0%
踩一下
(0)
0%
------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片
栏目列表
将本文分享到微信
织梦二维码生成器
推荐内容