65.9K
CodeProject 正在变化。 阅读更多。
Home

多线程下载加速器控制台

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.94/5 (5投票s)

2012年2月24日

GPL3

2分钟阅读

viewsIcon

40742

downloadIcon

970

将 Linux 和其他 Unix 的轻量级下载加速器 Axel 移植到 NATIVE WIN32

引言

Axel 是一个轻量级的 Linux 和其他 Unix 系统的下载加速器。它应该可以在 BSD、Solaris、Darwin (Mac OS X) 和 Win32 (Cygwin) 系统上编译和运行。

移植到原生 WIN32,无需 Cygwin,例如我在 #if WIN32 #endif 中所做的工作

  • 将 Linux 文件描述符用于新的套接字,更改为 WIN32 SOCKET 描述符,引用新的套接字
  • closewriteread 更改为 closesocketsendrecv
  • select 阻塞线程更改为 WSAEventSelect 异步 I/O
  • 将线程的 pthread_t 更改为引用线程的 HANDLE
  • pthread_createpthread_joinpthread_cancel 更改为 CreateThreadWaitForSingleObjectTerminateThread
  • 将 Linux 文件描述符用于保存文件,更改为引用保存状态的 HANDLE
  • openreadwriteclose 更改为 CreateFileReadFileWriteFileCloseHandle

背景

调试 Axel 以查看多线程下载方式

  • TCP 连接(socketbindconnect)到主机,例如由 IIS 提供的 https://
  • 发送 HTTP 头部请求
    GET / HTTP/1.0
    Host: www.codeproject.com
    Range: bytes=1-
    User-Agent: Axel 2.4 (WIN32)
  • 从头部回复中获取内容长度
    HTTP/1.1 206 Partial Content
    Content-Type: text/html
    Last-Modified: Tue, 20 Sep 2011 03:39:05 GMT
    Accept-Ranges: bytes
    ETag: "3c2bb1d84677cc1:0"
    Server: Microsoft-IIS/7.5
    X-Powered-By: ASP.NET
    Date: Fri, 24 Feb 2012 08:41:12 GMT
    Connection: close
    Content-Length: 688 /* Here is what I need */
    Content-Range: bytes 1-688/689
  • 将内容范围划分为线程数,例如 10
    Downloading 0-67 using conn. 0
    Downloading 68-136 using conn. 1
    Downloading 137-205 using conn. 2
    Downloading 206-274 using conn. 3
    Downloading 275-343 using conn. 4
    Downloading 344-412 using conn. 5
    Downloading 413-481 using conn. 6
    Downloading 482-550 using conn. 7
    Downloading 551-619 using conn. 8
    Downloading 620-688 using conn. 9
  • 通过其中一个线程发送带有范围 [from, to] 的 HTTP 头部请求
    GET / HTTP/1.0
    Host: localhost
    Range: bytes=206-274
    User-Agent: Axel 2.4 (WIN32)

SOCKET 接收 recv 缓冲区,将 HTTP 头部回复中的缓冲区写入 HANDLE CreateFile,使用临时文件 *.st(Axel 风格),下载内容范围后终止并关闭线程。临时文件有助于服务器主机恢复可用性。

Using the Code

源代码文件 text.c 是主入口,可以被视为一个很好的示例和测试用例,说明如何使用 Axel API。

conf_t conf;
conf_init(&conf);
conf.num_connections = 10;  /* multi-thread numbers */
conf.add_header_count = 0;
/* axel_t object construct */
axel_t *axel = axel_new(&conf, 0, "https://");
strcpy(axel->filename, "filename.htm");
axel_open(axel);
axel_start(axel);
/* Have not downloaded the total content */
while (!axel->ready) 
{
    axel_do(axel);
    /* printf some verbose about download threads info such as speed and complete percent */
}
/* axel_t object destruct */
axel_close(axel);

关注点

跨平台开发 - 在 Gentoo Linux 下使用 Axel 控制台来查看多线程下载加速器的工作方式,然后使用原生 WIN32 API 移植到 Windows。我在 Windows 7 64 位下使用 VS2005 编译源代码(选择 mbstring 项目设置,而不是 Unicode,这会导致 ^M CTRL-V CTRL-M、无法识别的中文字符和二进制文件垃圾问题),因此需要更多的贡献者在其他 Windows 发行版下进行调试。

改进

Windows Vista、7 和 Server 2008 才支持 WSAPoll,用于确定一个或多个套接字的的状态。它可能比 WSAEventSelect 更有效。

历史

  • 2012-02-27 xzhai 无 BUG :)
  • 2012-02-26 xzhai 
    • 修复了重新连接的错误
    • 修复了 BIGSIZE 文件冻结的错误
  • 2012-02-24 xzhai
    • 将 Axel v2.4 移植到无需 Cygwin 的 WIN32
© . All rights reserved.