原帖链接:http://www.0xaa55.com/thread-1093-1-1.html
别指望这东西有多强大的功能——它就是用来下载一个直链资源。给一个URL然后就能完成下载。目前只支持HTTP协议(以http://开头的链接)至于什么ED2K、种子、磁力链,或者ftp、https等,它是不支持的。
这个程序使用了Winsock库,TCP/IP协议。
原理就是建立一个SOCKET套接字(调用socket(AF_INET,SOCK_STREAM,IPPROTO_TCP)得到一个基于TCP/IP协议的SOCKET),分析要下载的文件的URL(比如http://www.baidu.com/img/bdlogo.png),取得协议(http://)、主机名(http://www.baidu.com)、路径(/img/bdlogo.png),然后建立一个http请求头,将其发送到服务器。服务器会回复一些内容,通过分析服务器发回的内容决定进一步的处理。
HTTP请求头是文本格式,一行一个描述符,然后以两个换行符为结尾。我直接参考了IE浏览器的HTTP请求头(用fiddler抓包)
通过参考了IE浏览器的HTTP请求头,我的下载器的请求头是这个样子的:
GET /路径 HTTP/1.1
Host: 域名
Connection: Keep-Alive
Accept: */*
Accept-Language: zh-CN
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko
如果我要从文件的中间开始下载,我的请求头会在这里添加Range: 开始字节-结束字节(其中结束字节是可选的)
我并不打算让我的下载器支持gzip、deflate,否则我就需要再给自己的代码整合一个zlib。
然后经过我的测试,当我下载一个7z文件的时候,服务器会返回这么一个HTTP头:
HTTP/1.1 200 OK
Date: Mon, 27 Oct 2014 14:10:09 GMT
Server: Apache
Last-Modified: Mon, 27 Oct 2014 07:32:24 GMT
Accept-Ranges: bytes
Content-Length: 内容大小
Connection: close
Content-Type: application/x-7z-compressed
如果Accept-Ranges的值是none,那么表示这个文件不能从中间开始下载,只能从头下载。
Content-Length大概是文件的大小,但是并不是每种MIME类型都会提供这个域,如果我是要下载一个纯文本、html文件,可能就没有Content-Length域。
而有些服务器因为资源被转移了,它会返回一个重定向信息。
HTTP/1.1 301 Moved Permanently
Date: Thu, 11 Dec 2014 10:53:19 GMT
Server: Apache/2.2.15 (CentOS)
Location: 新URL
Content-Length: 错误页面的大小
Connection: close
Content-Type: text/html; charset=字符集
这个时候就要注意第一行的HTTP/1.1后面的数字了,200是正常,3XX是重定向,4XX是无法访问特定资源,5XX一般是服务器错误或者其它。
如果是3XX重定向,我们就要注意Location域的内容,它指定了新的URL。
根据如上的经验,我写了这个简单的下载器。
经过测试,它能正确下载文件。


其中下载的文件是可以被正常打开的,有图为证:

而且对于3XX重定向的链接,它也能正确下载:


我这个程序使用了三个文件,为了使代码可复用。
download.c
download.h
entry.c
其中最重要的函数是DownFile,它的原型如下:
//=============================================================================
//函数:DownFile
//描述:根据指定的URL下载一个文件,返回下载的文件大小。
//用法:提供网络资源地址,以及一些可选的参数,然后使用两个回调函数取得下载到的
// 内容。下载到的内容通过fnOnGetData回调函数返回。
//-----------------------------------------------------------------------------
DownLDFunc(FileSize,DownFile)
(
char*szURL,//网络资源地址
int Limited,//是否限制大小
FileSize cbStartByte,//开始字节
FileSize cbEndByte,//结束字节
fnOnGetSize pfnGetSize,//取得下载到的数据的大小时调用的函数
fnOnGetData pfnGetData,//取得下载到的数据时调用的函数
fnErrReporter ErrReport,//报告错误的函数
void*pUserData//传递给用户回调函数的用户自定义参数
);
要下载源码请访问原帖:http://www.0xaa55.com/forum.php?mod=viewthread&tid=1093
别指望这东西有多强大的功能——它就是用来下载一个直链资源。给一个URL然后就能完成下载。目前只支持HTTP协议(以http://开头的链接)至于什么ED2K、种子、磁力链,或者ftp、https等,它是不支持的。
这个程序使用了Winsock库,TCP/IP协议。
原理就是建立一个SOCKET套接字(调用socket(AF_INET,SOCK_STREAM,IPPROTO_TCP)得到一个基于TCP/IP协议的SOCKET),分析要下载的文件的URL(比如http://www.baidu.com/img/bdlogo.png),取得协议(http://)、主机名(http://www.baidu.com)、路径(/img/bdlogo.png),然后建立一个http请求头,将其发送到服务器。服务器会回复一些内容,通过分析服务器发回的内容决定进一步的处理。
HTTP请求头是文本格式,一行一个描述符,然后以两个换行符为结尾。我直接参考了IE浏览器的HTTP请求头(用fiddler抓包)
通过参考了IE浏览器的HTTP请求头,我的下载器的请求头是这个样子的:
GET /路径 HTTP/1.1
Host: 域名
Connection: Keep-Alive
Accept: */*
Accept-Language: zh-CN
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko
如果我要从文件的中间开始下载,我的请求头会在这里添加Range: 开始字节-结束字节(其中结束字节是可选的)
我并不打算让我的下载器支持gzip、deflate,否则我就需要再给自己的代码整合一个zlib。
然后经过我的测试,当我下载一个7z文件的时候,服务器会返回这么一个HTTP头:
HTTP/1.1 200 OK
Date: Mon, 27 Oct 2014 14:10:09 GMT
Server: Apache
Last-Modified: Mon, 27 Oct 2014 07:32:24 GMT
Accept-Ranges: bytes
Content-Length: 内容大小
Connection: close
Content-Type: application/x-7z-compressed
如果Accept-Ranges的值是none,那么表示这个文件不能从中间开始下载,只能从头下载。
Content-Length大概是文件的大小,但是并不是每种MIME类型都会提供这个域,如果我是要下载一个纯文本、html文件,可能就没有Content-Length域。
而有些服务器因为资源被转移了,它会返回一个重定向信息。
HTTP/1.1 301 Moved Permanently
Date: Thu, 11 Dec 2014 10:53:19 GMT
Server: Apache/2.2.15 (CentOS)
Location: 新URL
Content-Length: 错误页面的大小
Connection: close
Content-Type: text/html; charset=字符集
这个时候就要注意第一行的HTTP/1.1后面的数字了,200是正常,3XX是重定向,4XX是无法访问特定资源,5XX一般是服务器错误或者其它。
如果是3XX重定向,我们就要注意Location域的内容,它指定了新的URL。
根据如上的经验,我写了这个简单的下载器。
经过测试,它能正确下载文件。


其中下载的文件是可以被正常打开的,有图为证:

而且对于3XX重定向的链接,它也能正确下载:


我这个程序使用了三个文件,为了使代码可复用。
download.c
download.h
entry.c
其中最重要的函数是DownFile,它的原型如下:
//=============================================================================
//函数:DownFile
//描述:根据指定的URL下载一个文件,返回下载的文件大小。
//用法:提供网络资源地址,以及一些可选的参数,然后使用两个回调函数取得下载到的
// 内容。下载到的内容通过fnOnGetData回调函数返回。
//-----------------------------------------------------------------------------
DownLDFunc(FileSize,DownFile)
(
char*szURL,//网络资源地址
int Limited,//是否限制大小
FileSize cbStartByte,//开始字节
FileSize cbEndByte,//结束字节
fnOnGetSize pfnGetSize,//取得下载到的数据的大小时调用的函数
fnOnGetData pfnGetData,//取得下载到的数据时调用的函数
fnErrReporter ErrReport,//报告错误的函数
void*pUserData//传递给用户回调函数的用户自定义参数
);
要下载源码请访问原帖:http://www.0xaa55.com/forum.php?mod=viewthread&tid=1093