libaria2:C++库接口到aria2¶
Warning
API尚未固定。它将在开发过程中被更改。
libaria2是一个C++库,提供aria2的核心功能。该库处理所有网络和下载相关的事务, 所以它的使用现在非常直接。查看以下教程部分了解如何使用API。
教程¶
本节是逐步指导创建一个使用libaria2下载文件的程序。完整的源代码位于 examples 目录下的 libaria2ex.cc。
libaria2ex 程序接受一个或多个URI,并且并行下载每个 文件。使用方式如下:
使用方式: libaria2ex URI [URI…]
在当前目录下并行下载给定的URI。
源代码使用C++11特性,因此需要支持C++11的编译器。 GCC 4.7在这里工作良好。
好的,让我们来看看源代码。首先,包含aria2.h头文件:
#include <aria2/aria2.h>
跳转到 main()
函数。在检查命令行
参数后,我们初始化libaria2:
aria2::libraryInit();
并创建aria2会话对象:
aria2::Session* session;
// 创建默认配置。libaria2处理信号
// 处理。
aria2::SessionConfig config;
// 添加事件回调
config.downloadEventCallback = downloadEventCallback;
session = aria2::sessionNew(aria2::KeyVals(), config);
Session
session
是一个aria2会话对象。您需要这个
对象贯穿整个下载过程。请记住,由于在aria2代码库中大量使用静态对象,每个进程只允许一个:type:Session`对象。:type:`Session`对象不适用于从多个线程并发访问。它必须一次从一个线程使用。一般来说,libaria2并不是完全线程安全的。:type:`SessionConfig config
保存会话对象的配置。构造函数使用默认值初始化它。在此设置中,SessionConfig::keepRunning
是
false
表示当所有下载都处理完毕时 run()
返回,就像没有启用RPC的aria2c工具一样。并且 SessionConfig::useSignalHandler
是 true
,意味着libaria2将设置信号处理器并捕获某些信号以优雅地停止下载过程。我们还设置了事件处理回调函数 downloadEventCallback
。当发生事件时,比如下载开始、完成等,它将被调用。在这个示例程序中,我们处理了两个事件:下载完成和错误。对于每个事件,我们打印下载的GID和其他几个
信息:
int downloadEventCallback(aria2::Session* session, aria2::DownloadEvent event,
const aria2::A2Gid& gid, void* userData)
{
switch(event) {
case aria2::EVENT_ON_DOWNLOAD_COMPLETE:
std::cerr << "COMPLETE";
break;
case aria2::EVENT_ON_DOWNLOAD_ERROR:
std::cerr << "ERROR";
break;
default:
return 0;
}
std::cerr << " [" << aria2::gidToHex(gid) << "] ";
...
}
userData
对象由
SessionConfig::userData
指定。在这个示例中,我们没有指定
它,所以它是 nullptr
。
sessionNew()
的第一个参数是 aria2::KeyVals()
。
这个类型在API中用于指定键/值对的向量,大多表示aria2选项。例如,指定选项
file-allocation
为 none
:
aria2::KeyVals options;
options.push_back(std::pair<std::string, std::string> ("file-allocation", "none"));
sessionNew()
的第一个参数类似于aria2c程序的
命令行参数。在示例程序中,我们没有提供任何选项,所以只需传递空向量。
在创建会话对象之后,让我们添加命令行中给出的下载:
// 将下载项添加到会话中
for(int i = 1; i < argc; ++i) {
std::vector<std::string> uris = {argv[i]};
aria2::KeyVals options;
rv = aria2::addUri(session, nullptr, uris, options);
if(rv < 0) {
std::cerr << "添加下载失败 " << uris[0] << std::endl;
}
}
我们迭代命令行参数并将每个参数作为一个单独的
下载添加。addUri()
可以接受一个或多个URI来下载
多个源,就像aria2c一样,但在这个例子中,我们只
给出了一个URI。我们没有为下载提供特定的选项,
所以传递空向量作为选项。addUri()
的第二个参数接受一个指向 A2Gid
的指针。如果它不是
NULL
,函数会将新下载的GID分配给它。在
这个示例代码中,我们对它不感兴趣,所以只需传递
nullptr
。
到目前为止,我们已经设置好了一切。所以让我们开始下载。为了
执行下载,反复调用 run()
直到它返回
不是 1
的值:
for(;;) {
rv = aria2::run(session, aria2::RUN_ONCE);
if(rv != 1) {
break;
}
...
}
这里,我们用 RUN_ONCE
调用 run()
。这意味着
run()
在一次事件轮询及其动作处理
或轮询超时(大约1秒)后返回。如果 run()
返回 1
,意味着下载正在进行中,应用程序必须再次调用它。如果它返回 0
,那么没有下载
剩余(或它被信号处理器或 shutdown()
停止)。
如果函数捕获错误,它返回 -1
。使用 RUN_ONCE
的好处是应用程序可以在 run()
返回时使用libaria2 API。在示例程序中,我们每隔不少于500毫秒打印一次
下载进度:
// 每500ms打印一次进度信息
if(count >= 500) {
start = now;
aria2::GlobalStat gstat = aria2::getGlobalStat(session);
std::cerr << "整体 #活跃:" << gstat.numActive
<< " #等待:" << gstat.numWaiting
<< " D:" << gstat.downloadSpeed/1024 << "KiB/s"
<< " U:"<< gstat.uploadSpeed/1024 << "KiB/s " << std::endl;
std::vector<aria2::A2Gid> gids = aria2::getActiveDownload(session);
for(const auto& gid : gids) {
aria2::DownloadHandle* dh = aria2::getDownloadHandle(session, gid);
if(dh) {
std::cerr << " [" << aria2::gidToHex(gid) << "] "
<< dh->getCompletedLength() << "/"
<< dh->getTotalLength() << "("
<< (dh->getTotalLength() > 0 ?
(100*dh->getCompletedLength()/dh->getTotalLength())
: 0) << "%)"
<< " D:"
<< dh->getDownloadSpeed()/1024 << "KiB/s, U:"
<< dh->getUploadSpeed()/1024 << "KiB/s"
<< std::endl;
aria2::deleteDownloadHandle(dh);
}
}
}
我们首先调用 getGlobalStat()
函数来获取下载的全局
统计信息。然后,调用 getActiveDownload()
函数来获取活动下载的GID向量。对于每个GID,我们
使用 getDownloadHandle()
函数检索 DownloadHandle
对象并获取详细信息。
请不要忘记在使用后和下一次调用 run()
之前删除 DownloadHandle
。请记住 DownloadHandle
对象的生命周期是在下一次调用 run()
之前。
循环结束后,调用 sessionFinal()
函数完成下载,并调用 libraryDeinit()
释放库的资源:
rv = aria2::sessionFinal(session);
aria2::libraryDeinit();
return rv;
调用 sessionFinal()
很重要,因为它执行下载后的操作,包括保存会话和销毁会话对象。因此,如果不调用此函数,将导致下载进度丢失和内存泄漏。sessionFinal()
返回在 退出状态 中定义的代码。aria2c 程序也返回相同的值作为退出状态,所以在这个小示例程序中也做同样的操作。
另请参见 libaria2wx.cc,它使用 wx GUI 组件作为用户界面,并使用后台线程运行下载。
API 参考¶
要使用 API 函数,请包含 aria2/aria2.h
:
#include <aria2/aria2.h>
所有枚举、类型和函数都在 aria2
命名空间下。要链接 libaria2,请使用链接器标志 -laria2
。