Aria2源代码分析——aria2 1.19.2

原创 2015年11月20日 16:46:43
Aria2源代码分析-aria2.1.19.2

1.src/main.cc
主程序入口,从命令行接受启动参数,判断系统类型,调用不同的context构造函数

2.context类/结构
Context(bool standalone, int argc, char** argv, const KeyVals& options);
standalone /*没搞懂这个变量的意义,但是目测在openwrt下就是true,不需要特意关注*/
KeyVals& options /*KeyVals是一个自定义指针,类似于字典的格式,对组.
 The type of Key/Value pairs.*/
typedef std::vector<std::pair<std::string, std::string> > KeyVals;

3.context构造函数实现,首先调用option_processing函数,基本就是解析启动参数,不用关注细节。
之后根据协议类型调用,判断是BT 是url 还是磁力链接
只分析BT 输入参数为 本地目录torrent文件,非URL,如此则调用createRequestGroupForBitTorrent

4.createRequestGroupForBitTorrent
/*这个做了一个重构函数,针对输入的是url的torrent地址或者是xxx.torrent文件,总之最终都转化为种子文件名*/
但是adjustAnnounceUri没有传值???之后又继续作为参数往下传递了??
之后调用createBtRequestGroup

5.createBtRequestGroup
/*adjustAnnounceUri在此函数中作为入参直接赋值为true,不清楚原因*/
auto rg = std::make_shared<RequestGroup>(gid, option);
auto dctx = std::make_shared<DownloadContext>();
/*这里创建了两个类指针,从而调用其构造函数*/
5.1 RequestGroup
构造函数初始化了一些下载用的参数,调用了两个初始化函数,继续深入……
initializePreDownloadHandler();
initializePostDownloadHandler();
/* 初始化下载句柄。。获取了BT下载的句柄*/
getBtPreDownloadHandler,getBtPostDownloadHandler
5.2 DownloadContext
设定一些下载参数,看命名应该是比如,文件大小,分片之类的

6.main.cc 之前遗漏。。,程序最重要的执行入口。。。
  if(context.reqinfo) {
    exitStatus = context.reqinfo->execute();
  }
  std::shared_ptr<MultiUrlRequestInfo> reqinfo;
/*因此首先调用MultiUrlRequestInfo中的 excute*/

7.error_code::Value MultiUrlRequestInfo::execute()
     try {
    e_->run();
  } catch(RecoverableException& e) 
  这里, e_是 std::unique_ptr<DownloadEngine> e_;
  所以接下来调用DownloadEngine中的 run

8.int DownloadEngine::run(bool oneshot)
    /*此cc中 run()->excuteCommand()->excute()
    这里的excute我觉得是 bool AbstractCommand::execute()
    此处是父类(抽象类?)的excute,根据命令的类型,去判断触发哪种下载模式的excute()???猜测
    这里用到了getDownloadEngine
    之前的一系列构造函数调用和初始化中,有调用到其对应的set宏*/

    /*AbstractCommand::execute(),基类的excute,其余所有子类继承之*/  

9.bool AbstractCommand::execute()
    这里是下载真正执行的地方:
    e_->poolSocket(req_, createProxyRequest(), socket_);
    DownLoadEngine poolSocket()此函数为下载 socket 线程池??重构四个形态
    SocketPoolEntry e(sock, std::move(timeout));
  poolSocket(createSockPoolKey(ipaddr, port, A2STR::NIL,proxyhost,proxyport),e);

10.纠正8中的excute问题, 原调用形式如下:
for(size_t i = 0; i < max; ++i) {
    auto com = std::move(commands.front());
    commands.pop_front();
    if (!com->statusMatch(statusFilter)) {
      com->clearIOEvents();
      commands.push_back(std::move(com));
      continue;
    }
    com->transitStatus();
    if (com->execute()) {
      com.reset();
    }
    else {
      com->clearIOEvents();
      com.release();
    }
  }
/*com是自动类型,因此这里调用的excute具体是哪个类中的excute完全看获取到的command,所以既可能是调用
基类AbstractCommand中的excute,也可能是bool FillRequestGroupCommand::execute()
纠正错误。AbstractCommand并非基类。。基类是Command。。。AbstractCommand DownLoadCommand 
FillRequestGroupCommand等等全是Command的子类*/

11.纠正前面的错误。。。。  AbstractCommand。。这个这个,应该列出一个从Command开始的类继承关系图。。
然而种类太多了。。。一一列举不能
那么关注此子类     PeerAbstractCommand
它的子类   PeerInitiateConnectionCommand
bool PeerInitiateConnectionCommand::executeInternal() {
  A2_LOG_INFO(fmt(MSG_CONNECTING_TO_SERVER,
                  getCuid(),
                  getPeer()->getIPAddress().c_str(),
                  getPeer()->getPort()));
  createSocket();
  getSocket()->establishConnection(getPeer()->getIPAddress(),
                                   getPeer()->getPort(), false);
这里创建了socket连接。。。    

12.继续探究Command基类的子类,发现TrackerWatcherCommand这个类应当是BT下载的实现
它的excute中 
if(!trackerRequest_) {
    trackerRequest_ = createAnnounce(e_);//此处是创建一个客户端宣告信息,貌似

下面看上去是轮询所有的tracker信息,每个tracker服务器都尝试去连接。。  
那么问题来了。。。种子解析在哪。。。

13.种子解析在之前提到过的context构造函数中……好吧,搞清楚了。。
#ifdef ENABLE_BITTORRENT
  if(!op->blank(PREF_TORRENT_FILE)) {
    if(op->get(PREF_SHOW_FILES) == A2_V_TRUE) {
      showTorrentFile(op->get(PREF_TORRENT_FILE));
      return;
    } else {
      createRequestGroupForBitTorrent(requestGroups, op, args,
                                      op->get(PREF_TORRENT_FILE));
    }
  }
/*是的。。就是这一段,blank是判断传进的字符串是否为空,这里的话就是判断你给没给torrent文件吧。。
op->get 是取那个参数的值。。那些宏都是Prefer指针。。有的是数字,有的是字符串,有的是true or false
详细的见Prefers.cc  就是属性(preferance)定义。。看文件的大概意思,应该是把这些不同的值,都归类为Pref指针
然后搞了一个数组把它们都串起来,抽象为一个id,或者一个key值。。你调用的aria2的时候应该给的就是关键字或者
id,然后程序自动转换成其所代表的意义。。。。大概是这样*/

/*言归正传,这里先判断了是否提供了torrent文件,之后判断你要做的是什么操作。。如果是show-file操作,
那么解析这个种子文件并且返回种子文件的内容。。什么uri啦。。announce啦。。等等,都给你打印在屏幕上吧
如果不是show-file,那么就创建RequestGroup了,在这里就有种子文件的解析。。*/
show-file分支,解析调用的是bittorrent::load()
createRequestGroup分支,调用的是 bittorent::LoadFromMemory()
他们都定义在 bittorent_helper.cc
仔细读一下就发现,其实这两个函数都是调用了bittorent::processRootDictionary()这个函数。。
这里就是详细的解析。。然后如果是create的动作,那么相关的信息,存储到 DownloadContext和TorrentAttribute
这两个类

14.到这里我觉得大致的BT下载框架解析完毕。。可以看到aria2用的是udp打洞(具体的可以看NAT穿越)来做P2P通信,
并没有用现成的bittorrent库之类的,但是基本思想是照抄的,即 client-tracker-client模式

15.如果还需要深入研究各种功能。。最好的办法我觉得是 从Command这一基类,找到它的子类。。挨个分析,树状遍历       
版权声明:本文为博主原创文章,未经博主允许不得转载。

一个好用的下载工具--Aria2

Aria2是一个很好用的下载工具,支持http、ftp、torrent等协议,通过多线程多链接加速下载,内存、cpu占用资源少。通过chrome的插件,能接管网页中的下载项和百度云盘资源的下载。 本文...
  • Dcatfly
  • Dcatfly
  • 2016年11月23日 23:15
  • 4358

利用Aria2和旧电脑打造一台下载机

利用这个下载神器—— Aria2,可以把你的旧电脑 / 手机变成一台免费的(电费除外)的 24 小时运行的下载机,比那些所谓的“离线下载”好多了 Aria2是全平台的,Windows、MAC、Lin...
  • XcantloadX
  • XcantloadX
  • 2017年10月14日 21:51
  • 874

aria2配置示例

 aria2配置示例 其实面对man的存在,写什么总结完全没有必要,一切宝藏都在manual。不过反正不会有人会读就是了。那我就写一下吧 ##基础 首先,aria2或者叫做aria2c...
  • cs9dn003
  • cs9dn003
  • 2016年09月22日 08:57
  • 9110

Aria2-不限速全平台下载利器

https://www.jianshu.com/p/bb9490ea1c4d
  • zzg_1990
  • zzg_1990
  • 2017年12月22日 15:27
  • 2275

Aria2-不限速全平台下载利器

之前写过一篇,发现浏览下载人数众多,所以抽出时间把相关资源更新、失效的链接剔除以及添加最新软件下载链接(2017/01/17)。 这次给大家介绍一个下载利器,之前玩路由器也听说过,然而那时候水平...
  • pengyuan_D
  • pengyuan_D
  • 2017年07月24日 10:33
  • 2368

mac上使用Aria2,完全摆脱百度云盘的限速10kb/s

使用aria2
  • biyongyao
  • biyongyao
  • 2017年06月17日 11:11
  • 3469

如何解除百度云盘下载文件限速

如何百度云下载满速方法思路为下载chrome插件处理百度云文件下载限速问题首先 下载科学工具 https://github.com/yinghuocho/firefly-proxy 全平台支持 ...
  • qq_33242907
  • qq_33242907
  • 2018年01月17日 17:24
  • 297

openwrt sdk下交叉编译aria2c

想要在路由器下安装一个下载工具,选择了aria2c,用到的操作系统openwrt。 下面是交叉编译的步骤: (1)在github上下载最新的aria2版本aria2-1.33.0.tar.xz (2...
  • sophieliucm
  • sophieliucm
  • 2018年01月04日 13:33
  • 63

ubuntu16.04中安装下载工具uget+aria2并配置Firefox

1.安装软件之前最好先更新一下依赖项,命令:     sudo apt-get update 2.安装uget可以直接从软件中心里面安装,或者直接使用名令行:     sudo apt-get ins...
  • xiaohouye
  • xiaohouye
  • 2017年01月18日 18:08
  • 16847

ubuntu安装配置aria2

安装:sudo apt-get install aria2sudo mkdir /etc/aria2 #新建文件夹 sudo touch /etc/aria2/aria2.session ...
  • crazycui
  • crazycui
  • 2016年08月14日 19:38
  • 2720
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Aria2源代码分析——aria2 1.19.2
举报原因:
原因补充:

(最多只允许输入30个字)