torrent磁力种子搜索_BT磁力搜索引擎

torrent磁力种子搜索_BT磁力搜索引擎,第1张

torrent磁力种子搜索_BT磁力搜索引擎 ltsession(会话)是最核心的,种子只有加入进去方可下载上传等动作。


session_handle: 主要负责对session的 *** 作。


torrent_handle: 主要负责对种子的 *** 作以及状态查询。


session.pop_alerts(): 可以获取从上次调用以来的所有新警报的列表。


每种特定类型的警报可能包括特定于消息类型的附加状态。


所有警报都实现一个message()函数,该函数输出警报消息的相关信息。


这可以方便地记录事件。


下面先针对各小功能进行代码实现,最好再整合一个完整的代码例子1. 添加种子/磁力(并下载)lt::session ses; //定义session对象lt::add_torrent_params p = lt::parse_magnet_uri("magnet:?xt=urn:btih:......"); // 解析磁力链接p.save_path = "."; // 设置保存到当前目录lt::torrent_handle h = ses.add_torrent(p); //添加到session,并获得其句柄(该句阻塞执行,有结果才返回)lt::session ses; //定义session对象auto ti = std::make_shared<lt::torrent_info>(torrentFilePath); //通过种子文件 定义 torrent_info对象lt::add_torrent_params p; p.ti = ti;//这儿很重要, 必须要中torrent_info对象传递进来p.save_path = ".";p.userdata = static_cast<void*>(new std::string(torrentFilePath)); //这根据自己需要而定具体数据ses.async_add_torrent(std::move(p)); //这儿是异步调用, 调完就离开,获取不到 session_handle以上为 通过磁力链接 和 torrent 种子这两种方式添加到session的简单例子。


torrent_info类又诸多构造函数,对象定义方法也因此非常多,根据需要选择合适的。


另外添加种子到session的方法有 同步调用(阻塞耗时)和异步调用(立即返回)两种,也根据需要选择。


2. 警报直接上代码讲解for (;;) { std::vector<lt::alert*> alerts; ses.pop_alerts(&alerts); //获取自上次调用以来的新警报列表 for (lt::alert const* a : alerts) { //遍历处理自己需要的警报。


std::cout << a->message() << std::endl; //打印警报信息 // 下面是针对各种类型的警报进行处理例子 if (lt::alert_cast<lt::torrent_finished_alert>(a)) { goto done; } if (lt::alert_cast<lt::torrent_error_alert>(a)) { goto done; } } std::this_thread::sleep_for(std::chrono::milliseconds(200));} done: std::cout << "done, shutting down" << std::endl;我们可以用‘警报掩码’抓取我们关心的警报(有很多种类),如下 :lt::settings_pack pack;pack.set_int(lt::settings_pack::alert_mask // 设置掩码 关心 下面三种掩码 , lt::alert::error_notification | lt::alert::storage_notification | lt::alert::status_notification);lt::session ses(pack);警报掩码 之 掩码类别警报类型3. 更新配置选项session启动后,可以通过调用 apply_settings() 更新配置,lt::settings_pack pack;pack.set_int(lt::settings_pack::alert_mask,lt::alert::status_notification); ses.apply_settings(pack); // 更新配置 alert_mask虽然这样可以更新配置,但有些设置最好在启动会话之前设置,比如 listen_interfaces,以避免出现竞争条件。


如果使用默认设置启动会话,然后立即更改它们,则仍会有一个应用默认设置的窗口。


更改设置可能会触发侦听套接字关闭和重新打开,并发送NAT-PMP、UPnP更新。


因此,将设置更新批处理到单个调用中通常是一个好主意。


4. 获取种子状态for(;;){ ses.post_torrent_updates(); // 发送 alert::status_notification std::this_thread::sleep_for(250); std::vector<lt::alert*> alerts; ses.pop_alerts(&alerts); //获取自上次调用以来的新警报列表 for (lt::alert const* a : alerts) { // 处理 state_update_alert if (state_update_alert* p = alert_cast<state_update_alert>(a)) { // 包含自上次调用以来更新的种子状态 std::vector<torrent_status> status = p->stauts; ...... } } ....}5. 恢复种子恢复下载时,BT引擎必须恢复正在下载种子的状态,特别是文件的哪些部分已下载, 有两种方法可以做到这一点:(1) 从磁盘读取已下载文件片段,并将其与预定的哈希值进行比较。


(2) 保存已下载的片段(和部分片段)的状态到磁盘,并在恢复时重新加载。


如果添加种子时没有提供恢复数据,那么libtorrent将默认使用上面第1点。


libtorrent有提供函数,实现保存恢复数据的功能:torrent_handle.save_resume_data(torrent_handle::save_info_dict); 调用该函数的时机:(1). 人为地选中某个种子, *** 作‘保存恢复数据’。


(2). 每个种子加载完成时。


(3). 关闭session之前。


注意:调用该函数并没将恢复数据保存到磁盘上面, 调用该函数后实际上会发出警报:save_resume_data_alert(若成功) 或 save_resume_data_failed_alert(若失败)else if (save_resume_data_alert* p = alert_cast<save_resume_data_alert>(a)){torrent_handle h = p->handle; // 获取torrent_handle,目的是获取torrent_statusauto const buf = write_resume_data_buf(p->params); // p->params为 add_torrent_params 类型torrent_status st = h.status(torrent_handle::query_save_path);save_file(resume_file(st.info_hash), buf); //保存恢复数据到名为info_hash(长度40)的文件中}else if (save_resume_data_failed_alert* p = alert_cast<save_resume_data_failed_alert>(a)){// 如果不需要保存恢复数据,可以不打印错误信息return p->error == lt::errors::resume_data_not_modified;}6. session对象的析构销毁默认情况下会话析构函数会被阻塞。


关闭时,需要联系追踪器以停止种子,其他未完成的 *** 作需要取消。


关闭有时可能需要几秒钟,主要是因为跟踪器没有响应(和超时)以及DNS服务器没有响应。


DNS查找在失控时尤其难以中止。


为了能够异步地开始销毁等待,可以调用session::abort()。


它返回一个session_proxy对象,它是一个句柄,用于在销毁会话状态时保持会话状态。


它故意不提供任何会话 *** 作,因为它正在关闭。


拥有session_proxy对象后,会话析构函数不会阻塞。


但是session_proxy析构函数却将被阻塞。


这可用于并行关闭多个会话或应用程序的其他部分。


7. 完整实例#include <iostream>#include <thread>#include <chrono>#include <fstream>#include <libtorrent/session.hpp>#include <libtorrent/add_torrent_params.hpp>#include <libtorrent/torrent_handle.hpp>#include <libtorrent/alert_types.hpp>#include <libtorrent/bencode.hpp>#include <libtorrent/torrent_status.hpp>#include <libtorrent/read_resume_data.hpp>#include <libtorrent/write_resume_data.hpp>#include <libtorrent/error_code.hpp>#include <libtorrent/magnet_uri.hpp>using clk = std::chrono::steady_clock;// 返回 种子各种状态的名称char const* state(lt::torrent_status::state_t s){ switch(s) { case lt::torrent_status::checking_files: return "checking"; case lt::torrent_status::downloading_metadata: return "dl metadata"; case lt::torrent_status::downloading: return "downloading"; case lt::torrent_status::finished: return "finished"; case lt::torrent_status::seeding: return "seeding"; case lt::torrent_status::allocating: return "allocating"; case lt::torrent_status::checking_resume_data: return "checking resume"; default: return "<>"; }}int main(int argc, char const* argv[]) try{if (argc != 2) { std::cerr << "usage: " << argv[0] << " <magnet-url>" << std::endl; return 1;} lt::settings_pack pack; pack.set_int(lt::settings_pack::alert_mask , lt::alert::error_notification | lt::alert::storage_notification | lt::alert::status_notification); lt::session ses(pack); clk::time_point last_save_resume = clk::now(); // 从磁盘加载恢复数据,并在添加磁力链接时传递它 std::ifstream ifs(".resume_file", std::ios_base::binary); ifs.unsetf(std::ios_base::skipws); std::vector<char> buf{std::istream_iterator<char>(ifs) , std::istream_iterator<char>()}; lt::add_torrent_params p = lt::read_resume_data(buf); lt::add_torrent_params magnet = lt::parse_magnet_uri(argv[1]); if (p.info_hash != magnet.info_hash) { //判断恢复数据和磁力链接是否匹配,以磁力链接为准 p = std::move(magnet); } p.save_path = "."; // 保存到当前目录 ses.async_add_torrent(std::move(p)); lt::torrent_handle h; //当我们收到add_torrent_alert时,我们设置它 for (;;) { std::vector<lt::alert*> alerts; ses.pop_alerts(&alerts); for (lt::alert const* a : alerts) { if (auto at = lt::alert_cast<lt::add_torrent_alert>(a)) { h = at->handle; } // 如果收到 torrent_finished_alert或torrent_error_alert,则退出程序 if (lt::alert_cast<lt::torrent_finished_alert>(a)) { h.save_resume_data(); goto done; } if (lt::alert_cast<lt::torrent_error_alert>(a)) { std::cout << a->message() << std::endl; goto done; } // resume data准备就绪,保存到磁盘文件 if (auto rd = lt::alert_cast<lt::save_resume_data_alert>(a)) { std::ofstream of(".resume_file", std::ios_base::binary); of.unsetf(std::ios_base::skipws); auto const b = write_resume_data_buf(rd->params); of.write(b.data(), b.size()); } if (auto st = lt::alert_cast<lt::state_update_alert>(a)) { if (st->status.empty()) continue; // 因为我们只有一个种子,所以我们知道 这个status是哪个种子的 lt::torrent_status const& s = st->status[0]; std::cout << "r" << state(s.state) << " " << (s.download_payload_rate / 1000) << " kB/s " << (s.total_done / 1000) << " kB (" << (s.progress_ppm / 10000) << "%) downloadedx1b[K"; std::cout.flush(); } } std::this_thread::sleep_for(std::chrono::milliseconds(200)); // post state_update_alert 更新种子输出状态 ses.post_torrent_updates(); // 每30秒保存恢复数据一次 if (clk::now() - last_save_resume > std::chrono::seconds(30)) { h.save_resume_data(); last_save_resume = clk::now(); } } // 理想情况下,我们应该在这里保存恢复数据done: std::cout << "ndone, shutting down" << std::endl;}catch (std::exception& e) { std::cerr << "Error: " << e.what() << std::endl;}

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/tougao/645940.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-17
下一篇 2022-04-17

发表评论

登录后才能评论

评论列表(0条)

保存