posts - 23,  comments - 20,  trackbacks - 0
费了九牛二虎之力  终于让我把二弄出来了...
不好弄啊  本来都准备算了
哎  技术人员  哪能那么简单说放弃 ...
最后用了一个最笨的方法终于实现了要求

这次由于时间很匆忙  所以 界面方面没有做任何工作  速度的计算也没有 
本来是准备用线程池的  试验了一下  最后还是做老本行吧...自己创建线程
没有什么多任务方面的概念   就是一个简单的多线程的Demo
上代码吧...头疼  代码很烂  不要丢砖头

下载地址 HttpDownload MultiThread.rar
实现文件

  1 /***************************************************************************************
  2 *文件名称: HttpDownload MultiThreadDlg.cpp
  3 *文件说明: 测试自己写的多线程文件下载
  4 *思路说明: 利用最笨的方法  五个线程 每个线程写入一个文件 然后最后由主线程来组装成完整
  5 *          的文件
  6 *作    者: 李佳
  7 *完成时间: 09.8.18
  8 **************************************************************************************/
  9 
 10 #include "stdafx.h"
 11 #include "HttpDownload MultiThread.h"
 12 #include "HttpDownload MultiThreadDlg.h"
 13 #include "HttpSocket.h"
 14 #include "MyStruct.h"
 15 #pragma comment(lib , "Http.lib")
 16 
 17 #define  MAX_THREAD_NUM 3        //最大线程数量
 18 
 19 #ifdef _DEBUG
 20 #define new DEBUG_NEW
 21 #endif
 22 DWORD WINAPI DownloadThreadProc(LPVOID pDate);
 23 
 24 CHttpDownloadMultiThreadDlg::CHttpDownloadMultiThreadDlg(CWnd* pParent /*=NULL*/)
 25     : CDialog(CHttpDownloadMultiThreadDlg::IDD, pParent)
 26     , m_strSpeed(_T(""))
 27     , m_strStorgePath(_T(""))
 28     , iCount(0)
 29     , m_strDownloadAddr(_T("http://www.vckbase.com/code/network/internet/testhttp.rar"))
 30     , iGetNum(0)
 31 {
 32     m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
 33 }
 34 
 35 void CHttpDownloadMultiThreadDlg::DoDataExchange(CDataExchange* pDX)
 36 {
 37     CDialog::DoDataExchange(pDX);
 38     DDX_Text(pDX, IDC_EDIT3, m_strSpeed);
 39     DDX_Text(pDX, IDC_EDIT2, m_strStorgePath);
 40     DDX_Text(pDX, IDC_EDIT1, m_strDownloadAddr);
 41     DDX_Control(pDX, IDC_PROGRESS1, m_DownloadProg);
 42 }
 43 
 44 BEGIN_MESSAGE_MAP(CHttpDownloadMultiThreadDlg, CDialog)
 45     ON_WM_SYSCOMMAND()
 46     ON_WM_PAINT()
 47     ON_WM_QUERYDRAGICON()
 48     ON_MESSAGE(WM_USER_UICHANGE , ChangeUI)
 49     //}}AFX_MSG_MAP
 50     ON_BN_CLICKED(IDOK, &CHttpDownloadMultiThreadDlg::OnBnClickedOk)
 51     ON_BN_CLICKED(IDCANCEL, &CHttpDownloadMultiThreadDlg::OnBnClickedCancel)
 52     ON_BN_CLICKED(IDOK2, &CHttpDownloadMultiThreadDlg::OnBnClickedGetFilePath)
 53 END_MESSAGE_MAP()
 54 
 55 
 56 // CHttpDownloadMultiThreadDlg 消息处理程序
 57 
 58 BOOL CHttpDownloadMultiThreadDlg::OnInitDialog()
 59 {
 60     CDialog::OnInitDialog();
 61 
 62     // 将“关于”菜单项添加到系统菜单中。
 63 
 64     // IDM_ABOUTBOX 必须在系统命令范围内。
 65     ASSERT((IDM_ABOUTBOX & 0xFFF0== IDM_ABOUTBOX);
 66     ASSERT(IDM_ABOUTBOX < 0xF000);
 67 
 68     CMenu* pSysMenu = GetSystemMenu(FALSE);
 69     if (pSysMenu != NULL)
 70     {
 71         CString strAboutMenu;
 72         strAboutMenu.LoadString(IDS_ABOUTBOX);
 73         if (!strAboutMenu.IsEmpty())
 74         {
 75             pSysMenu->AppendMenu(MF_SEPARATOR);
 76             pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
 77         }
 78     }
 79 
 80     // 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
 81     //  执行此操作
 82     SetIcon(m_hIcon, TRUE);            // 设置大图标
 83     SetIcon(m_hIcon, FALSE);        // 设置小图标
 84 
 85     // TODO: 在此添加额外的初始化代码
 86     ::InitializeCriticalSection(&cs);
 87     return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
 88 }
 89 
 90 void CHttpDownloadMultiThreadDlg::OnSysCommand(UINT nID, LPARAM lParam)
 91 {
 92     CDialog::OnSysCommand(nID, lParam);    
 93 }
 94 
 95 void CHttpDownloadMultiThreadDlg::OnPaint()
 96 {
 97     if (IsIconic())
 98     {
 99         CPaintDC dc(this); // 用于绘制的设备上下文
100 
101         SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
102 
103         // 使图标在工作区矩形中居中
104         int cxIcon = GetSystemMetrics(SM_CXICON);
105         int cyIcon = GetSystemMetrics(SM_CYICON);
106         CRect rect;
107         GetClientRect(&rect);
108         int x = (rect.Width() - cxIcon + 1/ 2;
109         int y = (rect.Height() - cyIcon + 1/ 2;
110 
111         // 绘制图标
112         dc.DrawIcon(x, y, m_hIcon);
113     }
114     else
115     {
116         CDialog::OnPaint();
117     }
118 }
119 
120 //当用户拖动最小化窗口时系统调用此函数取得光标
121 //显示。
122 HCURSOR CHttpDownloadMultiThreadDlg::OnQueryDragIcon()
123 {
124     return static_cast<HCURSOR>(m_hIcon);
125 }
126 
127 //确定按钮
128 void CHttpDownloadMultiThreadDlg::OnBnClickedOk()
129 {
130     if (m_strDownloadAddr == "" || m_strStorgePath == "")
131     {
132         AfxMessageBox("请输入下载地址或者保存路径");
133         return;
134     }    
135     //file.Open(m_strStorgePath , CFile::modeCreate | CFile::modeWrite);    
136     int iFileSize = GetFileSize();    //获取文件大小
137     //file.SetLength(iFileSize);        //创建一个空文件
138     iCount = iFileSize / (4096);    //分段
139     if(iFileSize%(4096))
140         iCount++;    //剩下的一个
141     
142     //本来是准备使用Windows自带的线程池  后来由于各种问题  中断了这个想法
143     HANDLE hThread[MAX_THREAD_NUM];
144     MYSTRUCT MyStruct[MAX_THREAD_NUM];
145     int iThreadWork = iFileSize / (MAX_THREAD_NUM - 1);
146     m_DownloadProg.SetRange(0 , iCount);        //进度条    
147     for (int i = 0 ; i < MAX_THREAD_NUM ; i++)    //创建线程
148     {
149         //PMYSTRUCT MyStruct = (PMYSTRUCT)new char[sizeof(MYSTRUCT)];        
150         MyStruct[i].iThreadNum = i;
151         MyStruct[i].strURL = m_strDownloadAddr;
152         MyStruct[i].iStart = iThreadWork * i ;
153         MyStruct[i].iTo = iThreadWork * (i + 1- 1;
154         if(MyStruct[i].iTo >= iFileSize)
155             MyStruct[i].iTo = iFileSize;
156         MyStruct->Dlg = this;
157         hThread[i] = ::CreateThread(NULL,0,DownloadThreadProc,(PVOID)&MyStruct[i],NULL,NULL);
158     }    
159     WaitForMultipleObjects(MAX_THREAD_NUM , hThread , TRUE , INFINITE);
160     
161     file.Open(m_strStorgePath , CFile::modeCreate | CFile::modeWrite);
162     CFile fileTemp;
163     for(int i = 0 ; i < MAX_THREAD_NUM ; i++)
164     {
165         CString strTemp;
166         int xLen = MyStruct[i].iTo - MyStruct[i].iStart + 1;
167         strTemp.Format("%d" , i);
168         fileTemp.Open(strTemp , CFile::modeRead);
169         //char * pContent = new char[xLen];
170         CHAR pContent[50000];    //简单起见 直接用了大数组
171         fileTemp.Read(pContent , xLen );
172         file.Write(pContent , xLen);
173         fileTemp.Close();
174 //        delete pContent;
175     }
176     file.Close();
177 }
178 
179 //退出按钮
180 void CHttpDownloadMultiThreadDlg::OnBnClickedCancel()
181 {    
182     OnCancel();
183 }
184 
185 //获取存储地址
186 void CHttpDownloadMultiThreadDlg::OnBnClickedGetFilePath()
187 {
188     UpdateData(TRUE);
189     if(m_strDownloadAddr == "")
190     {
191         AfxMessageBox("请输入下载地址" , MB_OK);
192         return ;
193     }
194 
195     CString strFileName = m_strDownloadAddr;
196     m_strStorgePath = GetStorgeFolde();
197 
198     while(strFileName.Find("/"!= -1)
199     {
200         int i = strFileName.Find("/");
201         strFileName = strFileName.Mid(i +1 , strFileName.GetLength() - i - 1);
202     }
203 
204     m_strStorgePath += strFileName;
205     UpdateData(FALSE);
206 }
207 
208 //获取存储的文件夹
209 CString CHttpDownloadMultiThreadDlg::GetStorgeFolde(void)
210 {
211     CString strFold;
212     BROWSEINFO   bi;  
213     TCHAR   buffer[MAX_PATH];  
214     ZeroMemory(buffer,   MAX_PATH);  
215     bi.hwndOwner   =   GetSafeHwnd();  
216     bi.pidlRoot   =   NULL;  
217     bi.pszDisplayName   =   buffer;  
218 
219     bi.lpszTitle   =   _T("选择一个文件夹");  
220     bi.ulFlags   =   BIF_EDITBOX;  
221     bi.lpfn   =   NULL;  
222     bi.lParam   =   0;  
223     bi.iImage   =   0;  
224 
225     LPITEMIDLIST   pList   =   NULL;  
226     if   ((pList   =   SHBrowseForFolder(&bi))   !=   NULL)  
227     {  
228         TCHAR   path[MAX_PATH];  
229         ZeroMemory(path,   MAX_PATH);  
230         SHGetPathFromIDList(pList,   path);  
231         strFold = path;
232         UpdateData(FALSE);        
233     }    
234     return strFold;
235 }
236 int CHttpDownloadMultiThreadDlg::GetFileSize(void)
237 {
238     CHttpSocket HttpSocket;
239     CString strServer , strObject ;
240     USHORT uPort;
241     DWORD dwServerType;
242     long lLenth;
243     const char * pRequestHeader = NULL;
244 
245     //通过URL获取相关参数
246     AfxParseURL(m_strDownloadAddr , dwServerType , strServer , strObject , uPort);
247     pRequestHeader = HttpSocket.FormatRequestHeader((LPTSTR)(LPCTSTR)strServer , (LPTSTR)(LPCTSTR)strObject , lLenth );
248     HttpSocket.Socket();
249     HttpSocket.Connect((LPTSTR)(LPCTSTR)strServer );
250     HttpSocket.SendRequest();
251     HttpSocket.SetTimeout(100);
252 
253     char szLength[15];
254     HttpSocket.GetField("Content-Length" , szLength , 15);
255     int iServerState = HttpSocket.GetServerState();
256     return atoi(szLength);    
257 }
258 
259 //更新进度条
260 LRESULT CHttpDownloadMultiThreadDlg::ChangeUI(WPARAM wParam, LPARAM lParam)
261 {    
262     iGetNum++;
263     m_DownloadProg.SetPos(iGetNum);        
264     return 1;
265 }
266 
267 //下载线程
268 DWORD WINAPI DownloadThreadProc(LPVOID pDate)
269 {
270     MYSTRUCT* Mystruct = (PMYSTRUCT)pDate;
271 
272     CHttpSocket HttpSocket;
273     CString strServer , strObject ;
274     USHORT uPort;
275     DWORD dwServerType;
276     long lLenth;
277     const char * pRequestHeader = NULL;
278 
279     //通过URL获取相关参数
280     AfxParseURL(Mystruct->strURL , dwServerType , strServer , strObject , uPort);
281     pRequestHeader = HttpSocket.FormatRequestHeader((LPTSTR)(LPCTSTR)strServer , (LPTSTR)(LPCTSTR)strObject , lLenth ,NULL , NULL ,
282                                 Mystruct->iStart ,  Mystruct->iTo );
283                                 /*分段传输*/
284     HttpSocket.Socket();
285     HttpSocket.Connect((LPTSTR)(LPCTSTR)strServer );
286     HttpSocket.SendRequest();
287     HttpSocket.SetTimeout(100);
288 
289 #ifdef _DEBUG
290     CString strTemp;
291     strTemp.Format("Start :  %d   to   %d  \r\n" , Mystruct->iStart , Mystruct->iTo);
292     TRACE(strTemp);
293 #endif    
294 
295     CFile file;    
296     CString strFormat;
297     strFormat.Format("%d" , Mystruct->iThreadNum);
298     file.Open(strFormat , CFile ::modeCreate | CFile::modeWrite);
299     int iFileSize = Mystruct->iTo - Mystruct->iStart;
300     int iComplete = 0;
301     char szDate[4096];
302     DWORD dwStartTime , dwEndTime;
303     int iCalc = 0;
304     while(iComplete < iFileSize)
305     {        
306         dwStartTime = GetTickCount();
307         int iRecvNum = HttpSocket.Receive(szDate , 4096);
308         dwEndTime = GetTickCount();
309         if (iRecvNum == 0)
310         {
311             ::AfxMessageBox("服务器关闭链接");
312             return 0;
313         }
314         if (iRecvNum == -1)
315         {
316             ::AfxMessageBox("接收数据超时");
317             return 0;
318         }    
319     //    int iSpeed = 4096 / (dwStartTime - dwEndTime);
320         file.Write(szDate , iRecvNum);
321         iComplete += iRecvNum;
322 //        strFormat.Format("%d" , iSpeed);
323         //SendMessage(Mystruct->Dlg->m_hWnd  , WM_USER_UICHANGE , 0 , 0);
324     //    Mystruct->Dlg->m_strSpeed = strFormat;
325         /*if (iCalc >3)
326         {
327             Mystruct->Dlg->UpdateData(FALSE);
328             iCalc = 0;
329         }        */
330     }    
331     return 1;
332 }
333 
334 

头文件
 1 // HttpDownload MultiThreadDlg.h : 头文件
 2 //
 3 
 4 #pragma once
 5 #include "afxcmn.h"
 6 #include "afx.h"
 7 
 8 typedef struct _Mystruct
 9 {
10     CString strURL;        //链接
11     int iStart ;                //传送文件的起点
12     int iTo;                //终点
13     int iThreadNum;        //线程标示符    
14     CHttpDownloadMultiThreadDlg * Dlg;
15 }MYSTRUCT , *PMYSTRUCT;
16 // CHttpDownloadMultiThreadDlg 对话框
17 class CHttpDownloadMultiThreadDlg : public CDialog
18 {
19 // 构造
20 public:
21     CHttpDownloadMultiThreadDlg(CWnd* pParent = NULL);    // 标准构造函数
22 
23 // 对话框数据
24     enum { IDD = IDD_HTTPDOWNLOADMULTITHREAD_DIALOG };
25 
26     protected:
27     virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持
28 // 实现
29 protected:
30     HICON m_hIcon;
31 
32     // 生成的消息映射函数
33     virtual BOOL OnInitDialog();
34     afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
35     afx_msg void OnPaint();
36     afx_msg HCURSOR OnQueryDragIcon();
37     DECLARE_MESSAGE_MAP()
38 public:
39     CString m_strSpeed;
40     CString m_strStorgePath;
41     CString m_strDownloadAddr;
42     afx_msg void OnBnClickedOk();
43     afx_msg void OnBnClickedCancel();
44     afx_msg void OnBnClickedGetFilePath();
45     LRESULT ChangeUI (WPARAM , LPARAM);
46     CProgressCtrl m_DownloadProg;
47     CString GetStorgeFolde(void);
48 private:
49     int GetFileSize(void);
50     int iCount;
51     
52 public:
53     CFile file;
54     CRITICAL_SECTION cs;    //临界区
55     /*typedef struct _Mystruct
56     {
57         CHttpDownloadMultiThreadDlg * Dlg;
58         int iFileDownloadPos;
59     }MYSTRUCT , *PMYSTRUCT;
60     MYSTRUCT Mystruct;*/
61     int iGetNum;
62 };
63 
64 

本来要上个效果图  其实没必要 需要测试的朋友自己测试一下吧  
经常出现超时问题  不知道如何解决 自己找找Http类的Bug吧

posted on 2009-08-18 17:28 李佳 阅读(418) 评论(0)  编辑 收藏 引用

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理


<2009年8月>
2627282930311
2345678
9101112131415
16171819202122
23242526272829
303112345

常用链接

留言簿

随笔分类

随笔档案

文章档案

相册

搜索

  •  

最新评论

阅读排行榜

评论排行榜