Aria2源代码分析——aria2 1.19.2
2015-11-20 16:46
169 查看
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这一基类,找到它的子类。。挨个分析,树状遍历
相关文章推荐
- loadrunner中lr_log_message和lr_output_message 的区别
- 07(maven+SSH)之springmvc乱码问题
- python 例外与异常mac地址
- PHP的三种XML解析器之SimpleXML解析器(三)
- Python刷题笔记(5) - 判断“幸运数”
- MATLAB R2014a 中文版下载安装图文教程
- The fisr scan script coded by python
- Java零散知识点学习记录
- To Summarize the Error of Ipython Notebook
- Asp.Net Thread is being Aborted
- Getting Started with Salt Stack-the Other Configuration Management System Built with Python
- 通过代码添加约束之NSLayoutConstraint
- myeclipse building workspace如何禁止及提高myeclipse速度
- PHP语法(一):基础和变量
- python Queue的多线程应用
- java 中计算两个时间相差天数
- C#窗体多语言切换(简繁)
- 【ThinkPHP】验证码以及登陆例子
- Java语言实现的装饰设计模式复习
- spring整合struts2时action里的service注入不进来,