Chinaunix首页 | 论坛 | 博客
  • 博客访问: 229933
  • 博文数量: 59
  • 博客积分: 1215
  • 博客等级: 少尉
  • 技术积分: 575
  • 用 户 组: 普通用户
  • 注册时间: 2011-11-09 02:18
文章分类

全部博文(59)

文章存档

2012年(53)

2011年(6)

分类: LINUX

2012-01-12 00:20:00

    在仔细阅读代码之前,需要先研究一下Axel的数据结构。
  1. typedef struct
  2. {
  3.     conn_t *conn;
  4.     conf_t conf[1];
  5.     char filename[MAX_STRING];
  6.     double start_time;
  7.     int next_state, finish_time;
  8.     long long bytes_done, start_byte, size;
  9.     int bytes_per_second;
  10.     int delay_time;
  11.     int outfd;
  12.     int ready;
  13.     message_t *message;
  14.     url_t *url;
  15. } axel_t;

    首先是axel_t,显然,这是一个对每一个任务创建的结构体,包括了conn_t结构体,conf结构体,文件名,大小,速度,延迟,url等等,注意到前两个结构体我们还不知道是什么呢。。。。好吧,那就看看吧。。。

 

  1. typedef struct
  2. {
  3.     conf_t *conf;
  4.     
  5.     int proto;
  6.     int port;
  7.     int proxy;
  8.     char host[MAX_STRING];
  9.     char dir[MAX_STRING];
  10.     char file[MAX_STRING];
  11.     char user[MAX_STRING];
  12.     char pass[MAX_STRING];
  13.     
  14.     ftp_t ftp[1];
  15.     http_t http[1];
  16.     long long int size;        /* File size, not 'connection size'..    */
  17.     long long int currentbyte;
  18.     long long int lastbyte;
  19.     int fd;
  20.     int enabled;
  21.     int supported;
  22.     int last_transfer;
  23.     char *message;
  24.     char *local_if;

  25.     int state;
  26.     pthread_t setup_thread[1];
  27. } conn_t;

    根据名称猜测,这是有关下载任务的连接的属性,通过这个结构体来建立TCP连接及上层的FTP、HTTP连接,因为Axel是多线程的,所以还包括了pthread_t ,通过名字我猜这个setup_thread是在建立连接的时候有用到,因为暂时还没看到,所以先不管。

    接下来,是conf_t:

  1. typedef struct
  2. {
  3.     char default_filename[MAX_STRING];
  4.     char http_proxy[MAX_STRING];
  5.     char no_proxy[MAX_STRING];
  6.     int strip_cgi_parameters;
  7.     int save_state_interval;
  8.     int connection_timeout;
  9.     int reconnect_delay;
  10.     int num_connections;
  11.     int buffer_size;
  12.     int max_speed;
  13.     int verbose;
  14.     int alternate_output;
  15.     
  16.     if_t *interfaces;
  17.     
  18.     int search_timeout;
  19.     int search_threads;
  20.     int search_amount;
  21.     int search_top;

  22.     int add_header_count;
  23.     char add_header[MAX_ADD_HEADERS][MAX_STRING];
  24.     
  25.     char user_agent[MAX_STRING];
  26. } conf_t;

      真是一个比一个长了,不过都长不到哪里去。可以看到里面有最大速度、buffer大小、有木有代理等等配置信息。以后看到的时候再来一个一个分析吧。。。

      Good,三个接下来涉及到的数据结构都看到了,我们接下来分析一下新建任务的函数。

  1. axel_t *axel_new( conf_t *conf, int count, void *url )
  2. {
  3.     search_t *res;
  4.     axel_t *axel;
  5.     url_t *u;
  6.     char *s;
  7.     int i;
  8.     
  9.     axel = malloc( sizeof( axel_t ) );
  10.     memset( axel, 0, sizeof( axel_t ) );
  11.     *axel->conf = *conf;
  12.     axel->conn = malloc( sizeof( conn_t ) * axel->conf->num_connections );
  13.     memset( axel->conn, 0, sizeof( conn_t ) * axel->conf->num_connections );
  14.     if( axel->conf->max_speed > 0 )
  15.     {
  16.         if( (float) axel->conf->max_speed / axel->conf->buffer_size < 0.5 )
  17.         {
  18.             if( axel->conf->verbose >= 2 )
  19.                 axel_message( axel, _("Buffer resized for this speed.") );
  20.             axel->conf->buffer_size = axel->conf->max_speed;
  21.         }
  22.         axel->delay_time = (int) ( (float) 1000000 / axel->conf->max_speed * axel->conf->buffer_size * axel->conf->num_connections );
  23.     }
  24.     if( buffer == NULL )
  25.         buffer = malloc( max( MAX_STRING, axel->conf->buffer_size ) );

       一开始就新建一个任务axel,进行相关的初始化,包括缓存大小、最大速率等,因为我刚开始看,暂时对这些初始化的用处还不太了解,不过可以先从名字猜到一些的。

      继续往下看:

  1. if( count == 0 )
  2.     {
  3.         axel->url = malloc( sizeof( url_t ) );
  4.         axel->url->next = axel->url;
  5.         strncpy( axel->url->text, (char *) url, MAX_STRING );
  6.     }
  7.     else
  8.     {
  9.         res = (search_t *) url;
  10.         u = axel->url = malloc( sizeof( url_t ) );
  11.         for( i = 0; i < count; i ++ )
  12.         {
  13.             strncpy( u->text, res[i].url, MAX_STRING );
  14.             if( i < count - 1 )
  15.             {
  16.                 u->next = malloc( sizeof( url_t ) );
  17.                 u = u->next;
  18.             }
  19.             else
  20.             {
  21.                 u->next = axel->url;
  22.             }
  23.         }
  24.     }

      这段代码是把一系列的URL放到任务里面,url_t这个数据类型实际上是一个链表,之所以存放不止一个Url是因为服务器有多个镜像的原因。

      接下来~

 

  1. axel->conn[0].conf = axel->conf;
  2.     if( !conn_set( &axel->conn[0], axel->url->text ) )
  3.     {
  4.         axel_message( axel, _("Could not parse URL.\n") );
  5.         axel->ready = -1;
  6.         return( axel );
  7.     }

  8.     axel->conn[0].local_if = axel->conf->interfaces->text;
  9.     axel->conf->interfaces = axel->conf->interfaces->next;
  10.     
  11.     strncpy( axel->filename, axel->conn[0].file, MAX_STRING );
  12.     http_decode( axel->filename );
  13.     if( *axel->filename == 0 )    /* Index page == no fn        */
  14.         strncpy( axel->filename, axel->conf->default_filename, MAX_STRING );
  15.     if( ( s = strchr( axel->filename, '?' ) ) != NULL && axel->conf->strip_cgi_parameters )
  16.         *s = 0;        /* Get rid of CGI parameters        */
  17.     
  18.     if( !conn_init( &axel->conn[0] ) )
  19.     {
  20.         axel_message( axel, axel->conn[0].message );
  21.         axel->ready = -1;
  22.         return( axel );
  23.     }

    这段代码,第一行初始化配置,然后是解析Url(conn_set这个函数),根据结果初始化axel里面的一个从conn_t类型的成员变量。接下来初始化interface,这个暂时先搁着,后面会说到。接着解析文件名,进行conn_init即初始化conn_t的一个变量。

  1. /* This does more than just checking the file size, it all depends
  2.      on the protocol used.                    */
  3.     if( !conn_info( &axel->conn[0] ) )
  4.     {
  5.         axel_message( axel, axel->conn[0].message );
  6.         axel->ready = -1;
  7.         return( axel );
  8.     }
  9.     s = conn_url( axel->conn );
  10.     strncpy( axel->url->text, s, MAX_STRING );
  11.     if( ( axel->size = axel->conn[0].size ) != INT_MAX )
  12.     {
  13.         if( axel->conf->verbose > 0 )
  14.             axel_message( axel, _("File size: %lld bytes"), axel->size );
  15.     }
  16.     
  17.     /* Wildcards in URL --> Get complete filename            */
  18.     if( strchr( axel->filename, '*' ) || strchr( axel->filename, '?' ) )
  19.         strncpy( axel->filename, axel->conn[0].file, MAX_STRING );
  20.     
  21.     return( axel );
  22. }

     这一段有注释(怎么就这一段有。。。),就偷点懒。。不说了。。。呵呵

    新建任务就说到这里了,肯定有很多说的不对,等大神来指点指点。

阅读(2238) | 评论(3) | 转发(1) |
给主人留下些什么吧!~~

gsnumen2012-08-20 18:14:14

使用axel遇到 一个问题:


axel运行一段时间后, 就不再下载数据, 用strace跟踪发现,axel在不断的调用pthread_create(),而被创建的 thread 停止在
futex(0xb77bcde0, FUTEX_WAIT_PRIVATE, 2, NULL <unfinished ...>
In main thread , 因为设置了20秒超时
if( gettime() > axel->conn.last_transfer + axel->conf->reconnect_delay
{
    pthread_cancel( *axel->conn.setup_thread );
    axel->conn.state = 0;
}
被创建的线程不断的被cancel. 就这样线程被不断的创建,又被不

define_shore_me2012-01-14 01:13:26

我是一粒糖: 结构是基础啊!~
不过觉得读别人的程序着实有点痛苦.....
嗯嗯  还好这个Axel的源码不多

我是一粒糖2012-01-12 21:44:17

结构是基础啊!~
不过觉得读别人的程序着实有点痛苦