楊青 周冬梅 王一飛
摘要:首先介紹了BT元信息文件及BT庫libtorrent的數(shù)據(jù)交互過程,然后對(duì)libtorrent的部分重要數(shù)據(jù)結(jié)構(gòu)進(jìn)行了分析與說明,提出了業(yè)務(wù)插件擴(kuò)展的使用方法。
關(guān)鍵詞:BT協(xié)議;libtorrent應(yīng)用;BT插件
中圖分類號(hào):TP393文獻(xiàn)標(biāo)識(shí)碼:A文章編號(hào):1009-3044(2012)07-1526-03
Analysis of Libtorrent s Application Based on BT Protocol
YANG Qing, ZHOU Dong- mei ,WANG Yi-fei
(College of Science and Technology, Chengdu University of Technology, Chengdu 610059, China)
Abstract: Firstly,introduced the bt element information file and bt-libtorrents interactive process.Secondly,analyzed some important data structure of libtorrent. Lastly,put forward the method of using plug-in extension of business.
Key words: BT protocol; libtorrent App; BT plug-in
在現(xiàn)今網(wǎng)絡(luò)通信中,BT作為p2p技術(shù)的一種已得到廣泛應(yīng)用。在開源的BT協(xié)議庫中,LibTorrent是C++語言BitTorrent開發(fā)庫,旨在提供高性能和良好代碼風(fēng)格的BT開發(fā)包。該開發(fā)包與其他包不同的是,它直接通過網(wǎng)絡(luò)堆棧抓取文件頁,其性能是官方客戶端的數(shù)倍,尤其在基于服務(wù)器的bt服務(wù)器端開發(fā)中頗為重要。
1 BT元信息文件
元信息文件(Metainfo File Structure)又稱為種子文件(.torrent),其結(jié)構(gòu)元信息文件里面的所有數(shù)據(jù)都是一個(gè)以B編碼的dictionary,包含下面列出的重要的鍵(key):
1) info鍵對(duì)應(yīng)的值為一字典(dictonary),描述要發(fā)布的文件信息,分單文件模式和多文件模式,其中共有鍵piece length的鍵值為每片(piece)的字節(jié)數(shù)(通常情況下2的n次方),共有鍵pieces的鍵值是所有片(piece)哈希值字符串,如piece0:hash0 piece1:hash1。
2) announce的鍵值為tracher服務(wù)器的URL地址。
2 libtorrent數(shù)據(jù)交互
在peer的交互中,客戶端首先向Tracker請(qǐng)求下載,同時(shí)包括本地資源的發(fā)布,服務(wù)器端Tracker響應(yīng)則包含客戶端請(qǐng)求的資源列表。
2.1 Peer客戶端的TRACKER請(qǐng)求報(bào)文(announce)
TRACKER請(qǐng)求報(bào)文(announce)的重要參數(shù)主要有:表示為元信息文件中的info鍵值(20字節(jié)哈希值)、表示為客戶端唯一ID的Peer_id、監(jiān)聽端口、客戶端uploaded情況、客戶端download情況和客戶端IP地址。
2.2 Tracker響應(yīng)報(bào)文(text/plain)
響應(yīng)文本由B編碼的字典(dictionary)組成,其中failure reason的鍵值表示可讀的錯(cuò)誤信息。Complete為完成整個(gè)文件下載的peer數(shù)以及peers鍵值為一個(gè)字典列表(peer的id、ip、port)。
2.3 Peer與Peer的交互過程
Peer與Peer的交互需要經(jīng)過握手,piece信息的發(fā)布以及piece的請(qǐng)求等過程,如圖1所示。
值得注意的是on_bitfield必須在handshake后立即發(fā)送,如peer無任何已下載了的piece也可以不發(fā)送bitfield。但在peer間通訊的其他時(shí)候不再允許發(fā)送此消息。
3 Libtorrent庫解析
libtorrent庫的接口由少量幾個(gè)類組成。最主要的類有session、entry、torrent_info、torrent_handle、alert、extensions。其內(nèi)部工作流程為如圖2所示。
圖1 Peer與Peer的交互過程示意圖
圖2 libtorrent內(nèi)部工作流程
3.1重要的數(shù)據(jù)結(jié)構(gòu)
3.1.1 entry類
在編碼體系結(jié)構(gòu)中,代表一個(gè)節(jié)點(diǎn)時(shí)可使用entry類。它可以是某個(gè)變量類型:鏈表(list)、字典(dictionary)、整數(shù)(integer)或者字符串(string等其中成員函數(shù)integer()、string()、list()、dict()函數(shù)是返回相應(yīng)類型的生產(chǎn)者。find_key()將在字典里查找指定關(guān)鍵字的元素,如從torrent信息文件中獲得信息的常用代碼:
dictionary_typeconst& dict = torrent_file.dict();
dictionary_type::const_iterator i=dict.find("announce");
if(i != dict.end()) {
std::string tracker_url = i->second.string();
std::cout << tracker_url << std::endl;}
3.1.2 torrent_info類
從torrent_info類中可以更快的從torrent信息文件中獲取信息,其中有懶惰接入對(duì)象的構(gòu)造函數(shù)將會(huì)從給定任務(wù)文件的信息中創(chuàng)建torrent_info對(duì)象。懶惰參數(shù)接入對(duì)象代表了編碼文件中的樹節(jié)點(diǎn)。為了加載一個(gè).torrent文件到一個(gè)懶惰接入對(duì)象中去,可以使用lazy_bdecode(), bdecode(), bencode()。值得一提的是含有一個(gè)哈希信息的構(gòu)造函數(shù)可用來初始化哈希信息,當(dāng)沒有元數(shù)據(jù)(metadata)或種子文件及無種下載時(shí),這個(gè)將會(huì)內(nèi)部使用,一旦元數(shù)據(jù)從群中下載,libtorrent將創(chuàng)建metadata。
3.1.3 torrent_handle類
對(duì)于管理單個(gè)事物,libtorrent提供了torrent_handle類來實(shí)現(xiàn)管理,如獲取torrent信息,自動(dòng)管理,上傳、下載設(shè)置,涉及的函數(shù)有
set_torrent_info()、save_resume_data()、auto_managed()、pause(),resume()、set_max_connections()、set_upload_limit(t)、set_download_limit()等。
其中save_resume_data(),可將一些狀態(tài)信息、資源下載情況等保存到指定文件(xx.resume)中,以便需要時(shí)能夠快速的恢復(fù)到之前的狀態(tài)繼續(xù)下載。
3.1.4 alert_manager類
告警是反應(yīng)系統(tǒng)運(yùn)行情況的一重要窗口,alert_manager::post_alert(const alert &alert)是從庫中獲得警告、消息、錯(cuò)誤的接口。如果隊(duì)列中沒有警告,post_alert()將返回一個(gè)默認(rèn)的初始化auto_ptr對(duì)象,否則將最前面的警告返回。通過session::set_alert_mask()用來指定哪類事件將被報(bào)告。如alert::error_notification(激活報(bào)告錯(cuò)誤的警告)、alert::peer_notification(對(duì)等點(diǎn)發(fā)送了非法請(qǐng)求,禁用,或沒有上傳或者下載時(shí)拋警告)、alert::progress_notification(塊被請(qǐng)求或者完成時(shí)警告)等.
在實(shí)際應(yīng)用開發(fā)中,特定的任務(wù)的警告都從alert類上面繼承,在libtorrent中提供了豐富的警告或錯(cuò)誤處理接口類,以及提供了進(jìn)行管理和處理的方式,如:
std::auto_ptr
while(alert *pAlert = a.get()){
if(torrent_finished_alert *pfinished =
alert_cast
{ .....
torrent_handle h = pfinished ->handle;h.save_resmue_data();
}
if(save_resume_data_alert*pResume=
alert_cast
{
torrent_handle h = p->handle;
......
std::cout<<"save resume data,name:"< } a = ses.pop_alert(); } 3.2業(yè)務(wù)插件的擴(kuò)展 擴(kuò)展是libtorrent的一大重要特點(diǎn),整個(gè)代碼的設(shè)計(jì)優(yōu)良,其為業(yè)務(wù)擴(kuò)展提供了便利。void add_extension(boost::function struct special_function_plugin: torrent_plugin { 重載相關(guān)成員函數(shù)(如on_files_checked(),on_piece_pass(),on_piece_failed()等}; struct special_function_peer_plugin: peer_plugin{ 重載相關(guān)成員函數(shù)(如on_handshake(),on_extension_handshake(),on_bitfield(),on_piece(),on_suggest()等}; boost::shared_ptr {bt_peer_connection *c =dynamic_cast if(!c) return boost::shared_ptr return boost::shared_ptr 4結(jié)束語 分析了bt協(xié)議的交互過程及交互中涉及的重要參數(shù)。同時(shí)對(duì)libtorrent的部分重要數(shù)據(jù)結(jié)構(gòu)進(jìn)行了簡要分析與說明,并給出了libtorrent的內(nèi)部工作流程。對(duì)于重要的數(shù)據(jù)結(jié)構(gòu)的使用提供部分偽代碼,提出了插件擴(kuò)展的使用方法,為快速的理解、使用libtorrent進(jìn)行開發(fā)提供了參考。 參考文獻(xiàn): [1] libtorrent document[EB/OL].http://libtorrent.rakshasa.no. [2] bittorrent document [EB/OL].http://www.bittorrent.com/. [3] bit protocol[EB/OL].http://www.bittorrent.com/.