接着上一篇,我们分析到了setup_thread这个函数,嗯嗯。。。开始要建立连接,也就是说要真正进入状态准备下载了。
可是建立连接要往下涉及到TCP套接字,究竟是自顶向下还是从下往上慢慢来呢。还是干脆就顺着代码走?这里用第一种方式,先宏观介绍,等以后谈到套接字的时候不辩自明。
好,我们先来看代码:
- void *setup_thread( void *c )
- {
- conn_t *conn = c;
- int oldstate;
-
- /* Allow this thread to be killed at any time. */
- pthread_setcancelstate( PTHREAD_CANCEL_ENABLE, &oldstate );
- pthread_setcanceltype( PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate );
-
- if( conn_setup( conn ) )
- {
- conn->last_transfer = gettime();
- if( conn_exec( conn ) )
- {
- conn->last_transfer = gettime();
- conn->enabled = 1;
- conn->state = 0;
- return( NULL );
- }
- }
-
- conn_disconnect( conn );
- conn->state = 0;
- return( NULL );
- }
比较关键的函数都是跟conn_t结构体相关的,我们先来分析conn_setup。
- int conn_setup( conn_t *conn )
- {
- if( conn->ftp->fd <= 0 && conn->http->fd <= 0 )
- if( !conn_init( conn ) )
- return( 0 );
-
- if( conn->proto == PROTO_FTP && !conn->proxy )
- {
- if( !ftp_data( conn->ftp ) ) /* Set up data connnection */
- return( 0 );
- conn->fd = conn->ftp->data_fd;
-
- if( conn->currentbyte )
- {
- ftp_command( conn->ftp, "REST %lld", conn->currentbyte );
- if( ftp_wait( conn->ftp ) / 100 != 3 &&
- conn->ftp->status / 100 != 2 )
- return( 0 );
- }
- }
- else
- {
- char s[MAX_STRING];
- int i;
- snprintf( s, MAX_STRING, "%s%s", conn->dir, conn->file );
- conn->http->firstbyte = conn->currentbyte;
- conn->http->lastbyte = conn->lastbyte;
- http_get( conn->http, s );
- http_addheader( conn->http, "User-Agent: %s", conn->conf->user_agent );
- for( i = 0; i < conn->conf->add_header_count; i++)
- http_addheader( conn->http, "%s", conn->conf->add_header[i] );
- }
- return( 1 );
- }
建立连接是有两种方式的,一种是FTP服务器的连接,另一个是HTTP。
这里先不展开来讲,大概说一下里面主要函数的作用:
先是FTP:
ftp_data函数是打开一个FTP连接,而且是用PASV命令即被动传输与FTP服务器连接,涉及到TCP连接等。
然后如果以前有下载过的,发个REST命令,接着读服务器状态。看看断点续传是不是正常的。状态为2或者3开头的就代表正常。
接着HTTP:
http_get把GET命令加到conn->request,同时加上其他的设定,譬如权限认证、传输起点和终点。
http_addheader把相应的命令对应的格式加到conn->request上,等下将会发送出去。
conn_setup函数这样就分析得差不多了。接下来,该是conn_exec了,真正开始接收文件了!!看代码!
- int conn_exec( conn_t *conn )
- {
- if( conn->proto == PROTO_FTP && !conn->proxy )
- {
- if( !ftp_command( conn->ftp, "RETR %s", conn->file ) )
- return( 0 );
- return( ftp_wait( conn->ftp ) / 100 == 1 );
- }
- else
- {
- if( !http_exec( conn->http ) )
- return( 0 );
- return( conn->http->status / 100 == 2 );
- }
- }
代码很短。在FTP中,发送RETR命令获得文件。在HTTP中的http_exec函数就是把刚才的conn->request发送出去。
好了~~~呼 可以回到文章开头的thread_setup了,大概就这样把连接都setup完,开始下载了。下一篇,我们的目光将又回到axel_start(其实这个函数介绍得差不多了)上,并且看看下载的过程~ 高潮来了
阅读(925) | 评论(0) | 转发(0) |