费了九牛二虎之力 终于让我把二弄出来了...
不好弄啊 本来都准备算了
哎 技术人员 哪能那么简单说放弃 ...
最后用了一个最笨的方法终于实现了要求
这次由于时间很匆忙 所以 界面方面没有做任何工作 速度的计算也没有
本来是准备用线程池的 试验了一下 最后还是做老本行吧...自己创建线程
没有什么多任务方面的概念 就是一个简单的多线程的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) 编辑 收藏 引用