Axel源码阅读笔记<一>
2011-10-30 15:24
183 查看
Axel源码阅读笔记<一>
一. Axel通过打开多个HTTP/FTP连接来将一个文件进行分段下载,从而达到加速下载的目的.对于下载大文件,该工具将特别有用.
它支持断点续传功能.其官方主页是:http://axel.sourcearchive.com.我这篇文章分析的是Axel的版本为:axel_2.4.orig.tar.gz
源码包下载链接:http://axel.sourcearchive.com/downloads/2.4/axel_2.4.orig.tar.gz
二.分析Axel的数据结构
Axel中共有7类用户自定义的数据结构,他们分别是:message_t,http_t,ftp_t,conn_t,conf_t,search_t,axel_t:
1.message_t:这是一个典型的通用链表结点类型的结构体.
typedef struct{
void *next;
char text[MAX_STRING];
}message_t;
只要学习过<<数据结构>>这本书的,基本都很熟悉这个结构.
源码中的axel.h文件中又将这个message_t分别定义为以下这两个类型:
typedef message_t url_t;//这个用于存储url
typedef message_t if_t;//这个用于存储本地ip列表
尽管名字不同(只是为了阅读达到见名知意的效果,当然这也是typedef的多数用途).
2.http_t:这个数据结构主要是在下载链接为ftp类型时使用.
typedef struct{
char host[MAX_STRING]; //表示http下载服务器的主机名称
char auth[MAX_STRING]; //为http验证信息,用来生成http头中的验证信息,其中user和pass都是根据你输入的URL地址来解析的
char request[MAX_QUERY]; //http请求的请求缓冲区
char headers[MAX_QUERY]; //axel中用来存储http响应消息的缓冲区.
//第一,存储正常的http响应消息,第二:存储http请求出错时的错误信息.
//还有,就是存储从输入的URL中解析后的参数.
//在http.c和conn.c中使用较多.
int proto; //存储协议 HTTP 或者FTP
int proxy; //是否使用代理的开关
long long int firstbyte;
long long int lastbyte; //下载的起始偏移和结束偏移,指定一个下载范围.(因为是多连接下载,因此每个连接都要分配一个下载范围的)
int status; //http每次请求的返回码.
int fd; //该http对应的连接的写文件的文件描述符.
char *local_if; //绑定的本地IP.
} http_t;
3.ftp_t:这个数据结构主要在下载链接为ftp类型时使用.
typedef struct{
char cwd[MAX_STRING]; //改变当前工作目录时,用来存储目录的缓冲区
char *message; //用来存储FTP操作的相关信息,比如错误信息,FTP服务器的返回信息等。
int status; //存储ftp操作的返回码
int fd; //类似于http中的、写文件的文件描述符
int data_fd; //FTP传输数据时,打开数据通道的socket描述符
int ftp_mode; //FTP传输模式,在axel中采用被动模式,正如作者在代码中说明的那样,只支持被动模式,这样简单.
char *local_if; //绑定本地的IP地址
}ftp_t;
4.conn_t:当Axel程序建立与服务器的链接时,这个结构体用于表示连接的信息.
typedef struct{
conf_t *conf; //配置信息,很明显,这个配置来源于axel初始化加载的配置
int proto; //协议,FTP或者HTTP
int port; //网络连接中使用的端口值,默认FTP为21,HTTP为80端口,如果你提供给axel的URL中包含了端口值的话,
//会解析并且使用指定的值.在axl中对conn->port赋值的有好几个情况.
//第一:从提供的URL中解析.第二:从系统的service文件中赋值.第三:默认值.
int proxy; //使用代理的标志位,0不使用代理,否则使用代理
char host[MAX_STRING]; //axel 接受的URL字符串存储的缓冲
char dir[MAX_STRING]; //axel接受的URL中解析的目录名称,比如 www.sina.con/url/book/*.mp3
//中conn->dir 为 /url/book.
char file[MAX_STRING]; //url的basename,如上面例子中的*.mp3
char user[MAX_STRING];
char pass[MAX_STRING]; //从url中解析的用户名和密码,如果是ftp协议的话,会写入匿名用户名和密码(默认值)ftp和http
ftp_t ftp[1];
http_t http[1]; //ftp和http下载时使用对象(上面已经解释过了)
long long int size; //要下载的文件总的大小(而不是一个连接应该下载的大小)
long long int currentbyte; //当前连接应该开始下载的位置,也就是每个连接的开始下载位置,比如1000字节文件,5个连接,每个连接的开
//始位置为1,201,401,601,801
long long int lastbyte; //当前连接结束下载的位置,比如1000字节文件,5个连接,每个连接的结束位置为200,400,600,800,1000
int fd; //每个连接网络通讯的socket描述符
int enabled; //用来标识连接的可用性,连接失败,或者传输失败时都会置为0
int supported; //测试是否支持FTP断点续传和重新尝试下载
int last_transfer; //一个连接最后一次进行网络传输的时间,用来做超时检测和下载速度计算
char *message; //存储网络连接中的返回值,错误信息,以及axel自身的报错等信息
char *local_if; //使用的本地主机地址列表
int state; //存储连接的状态,0无效,否则有效
pthread_t setup_thread[1]; //连接建立的线程函数体,在axel中每个线程的连接建立过程正好是通过一个叫setup_thread的线程来完成的
}conn_t;
5.conf_t:这个结构体主要用于存储axel的配置信息,axel会尝试从本地配置文件和环境变量中加载这些配置信息.
typedef struct{
char default_filename[MAX_STRING]; //存储时的默认文件名称
char http_proxy[MAX_STRING]; //http连接时代理服务器地址,axel首先会从环境变量中加载,如果没有配置的话,
//就尝试从本地配置文件加载http_proxy,如果找到的话,会在函数connect_init中调用,
//主要用于http_connect函数,最终会在conn_set函数中进行解析。
char no_proxy[MAX_STRING]; //不用任何代理服务器,因axel默认会从配置文件和环境变量中加载代理服务器,也即默认支持代理服务器的。
//在函数conn.c:conn_init中和conf.c:conf_init中是关于这个配置的具体操作。
int strip_cgi_parameters; //URL中是否扔掉cgi参数,也是从配置文件中加载
//比如 www.xxx.com?id=1&name=test
//如果开启的话,?后面的参数会被扔掉.默认该项为1.
int save_state_interval; //axel的每个下载连接,会在一定间隔后把当前连接的下载状态写到一个后缀为“.st”的状态文件中.这个项就
//是配置这个时间间隔的,默认为10秒,从配置文件中加载配置的值.
int connection_timeout; //每个连接的连接超时时间,如果连接失败了,会尝试重新连接,但是如果从开始到现在经过了
//connection_timeout时间还没连接上,就放弃默认是45秒,从配置文件中加载.
int reconnect_delay; //重连延迟,连接失败后,过过久再次去尝试连接,默认20秒,从配置文件加载值。
int num_connections; //分多个少个连接去下载,也就是-n后面输入的参数.默认为4个,从stdin和配置中加载.
int buffer_size; //通讯和写文件时采用缓冲的大小,从配置文件中加载.默认5120.
int max_speed; //最大下载速度,默认无限制,从配置中加载,一旦某个时刻计算的平均下载速度超过这个值的话,
//再次下载时就会睡眠多点时间,降低平均速度。
int verbose; //日志打印开关
int alternate_output; //打印进度的方式,也就是-a开启的功能,表示以scp或者wget方式打印进度。
if_t *interfaces; //通讯时使用的IP列表,从配置文件加载。
int search_timeout; //查找镜像文件超时,默认10秒,从配置文件加载。
int search_threads; //使用几个线程查找镜像文件,默认是3个,从配置文件加载。
int search_amount; //查找镜像文件的个数,默认是15个,从配置文件加载
int search_top; //从查找的镜像文件中获取速度最快的前几个作为下载源
int add_header_count; //添加http头的个数,从-H xx解析 比如 -H xxx -H yyy,获得值为2
char add_header[MAX_ADD_HEADERS][MAX_STRING];//添加的http头存储单元,最多允许添加10个header,每个限制长度为1024,从配置文件和stdin获取.
char user_agent[MAX_STRING]; //http头中的user-agent,从配置文件和stdin获取,-U后面的串。
}conf_t;
6.search_t:查找下载镜像其实这个不用介绍,都能可以猜出来:描述最终下载过程信息的结构体.
typedef struct{
char url[MAX_STRING]; //用来存储搜索到的镜像文件地址
double speed_start_time; //因为在计算速度时是通过一个时间段的时差或者这个时间段的下载量来计算的,因此每次计算都需要一个起始
int speed, size; //speed存储查找镜像后,各个镜像地址的响应的速度,实际上存储的是响应时间,时间越大,速度越小.
//size 用来存储各个站点下载的文件的大小,查找列表第一个位置的search_t中的size是源站点
//的文件大小,其它search_t的size是查找到的镜像文件的大小.
//当然镜像URL中获取的size如果和源不一样大,认为是错误的。
pthread_t speed_thread[1]; //测试线程,测试每个下载连接的下载速度用
conf_t *conf; //配置信息,从axel加载的配置中拷贝过来的
}search_t;
7.axel_t:其实这个不用介绍,都能可以猜出来:描述最终下载过程信息的结构体.
typedef struct{
conn_t *conn; //一个axel下载对象对应的连接
conf_t conf[1]; //一个axel下载对象的配置,是从axel初始化的conf中拷贝过来的
char filename[MAX_STRING]; //要下载的文件名
double start_time; //一个Axel开始下载的时间
int next_state, finish_time; //下一次写入状态文件的时间;
//结束下载的时间点;
long long bytes_done, start_byte, size; //已经下载了多少字节;
//开始下载的字节;
//要下载的文件大小
int bytes_per_second; //每秒平均下载字节数
int delay_time; //为了平滑下载速度,使得下载速度不要超过设定的限制,需要sleep一个时间段后
//再接着下载,delay_time就是这个时间间隔
int outfd; //写文件的文件描述符
int ready; //标志位,是否已经准备好下载了
message_t *message; //用来存储一个axel下载过程中的信息,日志等消息
url_t *url; //每个axel下载的来源URL,可能为源地址或者镜像文件地址
}axel_t;
(后续还有相关笔记,请大家一起探讨)
注解:期待有共同编程爱好的博友,批评指正,一起交流,共同学习.我的邮箱:opensourceroad@gmail.com
相关文章推荐
- QT核心机制分析1——信号与槽<一>
- mysql半同步复制<一>
- Cocos2d入门 <一>建立一个新工程
- cocos2d JS 自学笔记 <一> 初步接触cocos2d JS
- Universal-ImageLoader开源详解<一>
- oracle的使用<一>支持的数据类型
- JNI接口函数<一>
- Ajax学习笔记<一>
- <一>java数据结构与算法 数组
- 表驱动概述<一>
- Core Animation - 变换<一>
- Android binder 原理及实现机制<一>
- 程序员 7K面试题<一>---交通灯管理系统
- unity3d之Navigation <一>
- Eclipse+Maven创建webapp项目<一>
- JS---JavaScript面向对象编程<一>:封装
- (语法)内存地址和指针<一>
- Javascript Math 中常用函数<一>--ceil(),floor(),round()
- 树的学习<一>-----二叉树的遍历
- 机器学习入门指引<一>