Tracker HTTP/HTTPS Protocol
Tracker是一個(gè)響應(yīng)HTTP GET請(qǐng)求的HTTP/HTTPS服務(wù)。這個(gè)請(qǐng)求包含來自客戶端的度量信息,這些信息能夠幫助Tracker全面地統(tǒng)計(jì)torrent。Tracker的響應(yīng)包含一個(gè)peers列表,這個(gè)列表能夠幫助客戶端加入到torrent中。Base URL由元數(shù)據(jù)文件(即以.torrent為后綴的文件)中定義的announce URL組成,然后使用標(biāo)準(zhǔn)的CGI方式將這些請(qǐng)求參數(shù)追加到這個(gè)URL后面(CGI方式即在announce URL后面緊跟一個(gè)’?’,然后是一個(gè)以’&’分隔的’param=value’序列)。
注意:URL中的所有二進(jìn)制數(shù)據(jù)(特別是info_hash和peer_id)必須適當(dāng)?shù)剡M(jìn)行轉(zhuǎn)義。這意味著不在集合{0-9, a-z, A-Z, ‘.’, ‘-’, ‘_’, ‘~’}中的字節(jié)必須以’%nn’方式編碼,其中nn是這個(gè)字節(jié)的十六進(jìn)制值。
對(duì)于一個(gè)20字節(jié)的散列值 “\x12\x34\x56\x78\x9a\xbc\xde\xf1\x23\x45\x67\x89\xab\xcd\xef\
x12\x34\x56\x78\x9a”,其正確的編碼形式是“%124Vx%9A%BC%DE%F1%23Eg%89%AB%CD%EF
%124Vx%9A“。
Tracker Request Parameters
從客戶端發(fā)送到Tracker的請(qǐng)求包含如下參數(shù):
l info_hash:URL編碼的20字節(jié)SHA1散列,這個(gè)散列是元信息文件中info鍵所對(duì)應(yīng)的值的SHA1散列。注意info鍵所對(duì)應(yīng)的值是一個(gè)B編碼的dictionary,關(guān)于info鍵的定義請(qǐng)參考我的上一篇博文。
l peer_id:使用URL編碼的20字節(jié)串,用于標(biāo)識(shí)客戶端的唯一ID,由客戶端啟動(dòng)時(shí)生成。這個(gè)ID可以是任意值,甚至可能是二進(jìn)制數(shù)據(jù)。目前沒有生成該ID的標(biāo)準(zhǔn)準(zhǔn)則,盡管如此,實(shí)現(xiàn)者必須保證該ID對(duì)于本地主機(jī)是唯一的,因此可以通過包含進(jìn)程ID和啟動(dòng)時(shí)記錄的時(shí)間戳(timestamp)來達(dá)到這個(gè)目的。關(guān)于這個(gè)字段的常用客戶端編碼,請(qǐng)參考我的下一篇博文。
l port:客戶端正在監(jiān)聽的端口號(hào)。為BitTorrent協(xié)議保留的端口號(hào)是6881-6889。如果不能使用該區(qū)間的數(shù)字建立端口號(hào),客戶端有可能拒絕建立連接。
l uploaded:客戶端已經(jīng)上傳的總量(從客戶端發(fā)送’started’事件到Tracker算起),以十進(jìn)制ASCII表示。盡管官方規(guī)范沒有顯式指定,大部分情況下是指已經(jīng)下載的字節(jié)總數(shù)。
l downloaded:已下載的字節(jié)總量(從客戶端發(fā)送’started’事件到Tracker算起),以十進(jìn)制ASCII表示。盡管官方規(guī)范沒有顯式指定,大部分情況下是指已經(jīng)下載的字節(jié)總數(shù)。
l left:客戶端還沒有下載的字節(jié)數(shù),以十進(jìn)制ASCII表示。
l compact:如果設(shè)置為1,表示客戶端接收壓縮的響應(yīng)包。這時(shí)peers列表將被peers串代替,在這個(gè)peers串中,每個(gè)peer占六個(gè)字節(jié)。這六個(gè)字節(jié)的前四個(gè)字節(jié)表示主機(jī)信息(以大端表示即以網(wǎng)絡(luò)字節(jié)序),后兩個(gè)字節(jié)表示端口號(hào)(以大端表示即以網(wǎng)絡(luò)字節(jié)序)。需要注意的是,為了節(jié)約帶寬,有些Tracker只支持返回壓縮的響應(yīng)包,如果沒有將compact設(shè)置為1,Tracker將拒絕這個(gè)請(qǐng)求或者如果請(qǐng)求中不包括compact=0這個(gè)參數(shù),Tracker將返回壓縮的響應(yīng)包。
l no_peer_id:表示Tracker將省略peers dictionary中的id字段。如果啟用compact,那么就會(huì)忽略這個(gè)選項(xiàng)。
l event:如果指定的話,必須是started, completed, stopped和空(和不指定的意義一樣)中的一個(gè)。如果一個(gè)請(qǐng)求不指定event,表明它只是每隔一定間隔發(fā)送的請(qǐng)求。
n started:第一個(gè)發(fā)送到Tracker的請(qǐng)求其event值必須是該值。
n stopped:如果正常關(guān)閉客戶端,必須發(fā)送改事件到Tracker。
n completed:如果下載完畢,必須發(fā)送改事件到Tracker。如果客戶端啟動(dòng)之前,已經(jīng)下載完成的話,則沒有必要發(fā)送該事件。Tracker僅僅基于該事件增加已經(jīng)完成的下載數(shù)。
l ip:(可選),客戶主機(jī)的IP地址,點(diǎn)分十進(jìn)制IPv4或者RFC3513指定的十六進(jìn)制Ipv6地址。注意:一般情況下這個(gè)參數(shù)沒有必要,因?yàn)镮P地址可以從HTTP請(qǐng)求中得到。只有當(dāng)請(qǐng)求中的IP地址不是客戶端的IP地址時(shí),才需要這個(gè)參數(shù)(只有客戶端通過代理和tracker 交互時(shí)才會(huì)發(fā)生這種情況)。如果客戶端和Tracker都在NAT網(wǎng)關(guān)的同一側(cè),這個(gè)時(shí)候這個(gè)參數(shù)就是必要的。原因是Tracker會(huì)公布不能路由的客戶端物理地址。因此客戶端必須顯示指出自己的IP地址,以將信息公布給外部的peers。不同的Tracker對(duì)待該參數(shù)的方式不同。一些Tracker只有當(dāng)請(qǐng)求中的IP地址在RFC1918空間才使用它,有一些則無條件使用,另一些則根本不使用。如果是Ipv6地址,它表示這個(gè)客戶端只能通過IPv6交互。
l numwant:(可選),客戶端希望從Tracker接受到的peers數(shù),如果省略,則默認(rèn)是50個(gè)。
l key:(可選),不和其他用戶共享的附加標(biāo)識(shí)。當(dāng)客戶端IP地址改變時(shí),可以使用該標(biāo)識(shí)來證明自己的身份。
l trackerid:(可選),如果之前的announce包含一個(gè)tracker id,那么當(dāng)前的請(qǐng)求必須設(shè)置該參數(shù)。
Tracker Response
Tracker以”text/plain”文本響應(yīng)客戶端的請(qǐng)求,這個(gè)響應(yīng)文本由B編碼的dictionary組成,而這個(gè)dictionary則包含如下的鍵(key):
l failure reason:如果dictionary中包含這個(gè)鍵(key),那么其他的鍵(key)就不會(huì)出現(xiàn),該鍵(key)對(duì)應(yīng)的值是一個(gè)可讀的錯(cuò)誤消息,它告訴用戶的請(qǐng)求為什么會(huì)失敗。(字符串類型)
l warning message:(新加入,可選) 類似于failure reason,但是即使存在這個(gè)鍵,這個(gè)響應(yīng)還會(huì)正常地處理下去。warning message顯示為一個(gè)錯(cuò)誤。(字符串類型)
l interval:客戶端每隔一定間隔就會(huì)向Tracker發(fā)送一個(gè)請(qǐng)求,這個(gè)鍵(key)以秒為單位指出這個(gè)間隔的大小。(整數(shù)類型)
l min interval:(可選),最小的請(qǐng)求間隔,它表示客戶端不能在這個(gè)時(shí)間間隔之內(nèi)向Tracker重發(fā)請(qǐng)求。 (整數(shù)類型)
l tracker id:客戶端發(fā)送其下一個(gè)請(qǐng)求時(shí)必須返回給Tracker的一個(gè)字符串。如果缺失,但是上一個(gè)請(qǐng)求發(fā)送了tracker id,那么不要丟棄舊值,重復(fù)利用即可。
l complete:完成整個(gè)文件下載的peers數(shù),即做種者的數(shù)量。 (整數(shù)類型)
l incomplete:非做種的peers數(shù)(還沒有完成該文件下載的peers數(shù)),即“占他人便宜者”數(shù)。(整數(shù)類型)
l peers:(dictionary model) 該鍵(key)對(duì)應(yīng)的值是一個(gè)dictionary list(列表),該list中的每一個(gè)dictionary都包含如下的鍵(key):
n peer id:peer自己選擇的用來標(biāo)識(shí)自己的ID,上文在描述Tracker請(qǐng)求時(shí)已經(jīng)說明。 (字符串類型)
n ip:peer的IP地址,可以是Ipv6/Ipv4/DNS name。(字符串類型)
n port:peer的端口號(hào)。(整數(shù)類型)
l peers:(binary model) 不是使用上面描述的dictionary model,binary model下,該鍵(key)對(duì)應(yīng)的值可以有多個(gè)六字節(jié)組成的字符串。這六個(gè)字節(jié)中的前四個(gè)是IP地址,后兩個(gè)是端口號(hào)。IP地址和端口號(hào)均以網(wǎng)絡(luò)字節(jié)序(大端)表示。
綜上所述,默認(rèn)情況下peers列表的長(zhǎng)度是50,如果torrent中的peers比較少,那么這個(gè)列表長(zhǎng)度會(huì)更短。否則如果torrent中的peers比較多,那么tracker就得從這些peers中隨機(jī)選擇一些放入響應(yīng)中。當(dāng)響應(yīng)請(qǐng)求時(shí),Tracker需要使用一個(gè)智能的機(jī)制來進(jìn)行peer選擇。例如:向做種者報(bào)告種子就得避免(意思說如果沒有好的機(jī)制,就有可能出現(xiàn)這種情況)。
如果有一個(gè)事件發(fā)生(即stopped或者completed)或者客戶端需要獲得更多的peers時(shí),客戶端發(fā)送請(qǐng)求的頻率肯定高于指定的間隔。盡管如此,不斷地向Tracker發(fā)送請(qǐng)求以獲得更多的peers絕對(duì)不是一個(gè)好主意。如果一個(gè)客戶端想在其響應(yīng)中包含一個(gè)更長(zhǎng)的peer列表,那么它應(yīng)該通過指定numwant參數(shù)來達(dá)到目的。
BitTorrent實(shí)現(xiàn)者注意:30個(gè)peers已經(jīng)是一個(gè)很大的數(shù)目了,官方的客戶端版本3在peers少于30的情況,會(huì)積極地向Tracker建立連接已獲得更多的peers,但是如果客戶端已經(jīng)有55個(gè)peers的情況下,客戶端將拒絕和Tracker建立連接。這個(gè)值的選擇對(duì)于性能非常重要。當(dāng)一個(gè)片(piece)已經(jīng)下載完成后,客戶端需要將HAVE消息(參考下文)發(fā)送給大多數(shù)活躍的peers。結(jié)果是廣播通信的代價(jià)與peers數(shù)量成正比。這個(gè)數(shù)高于25之后,新加入的peers不太可能提升下載速度。強(qiáng)烈建議UI設(shè)計(jì)者使這個(gè)數(shù)模糊和很難修改,因?yàn)檫@樣做沒有任何作用。
Tracker 'scrape' Convention
按照慣例:大部分Tracker支持另一種形式的請(qǐng)求,這種方式查詢Tracker正在管理的給定torrent(或者所有的torrent)。這種方式通常被稱為”scrape page”,因?yàn)檫@種方式會(huì)自動(dòng)進(jìn)行另一個(gè)單調(diào)乏味的流程:”screen scraping” Tracker的統(tǒng)計(jì)頁。
類似于上面描述的URL,scrape URL也是一個(gè)HTTP GET方法。盡管如此,它們的Base URL是不相同的。想要得到scrape URL,請(qǐng)使用如下步驟:從announce URL開始,找到該announce URL中的最后一個(gè)’/’,如果該’/’之后的內(nèi)容不是’announce’,那么說明這個(gè)Tracker不支持scrape。如果這個(gè)Tracker支持scrape,那么使用’scrape’代替’announce’就可以得到scrape頁。
例:(announce URL -> scrape URL)
~http://example.com/announce -> ~http://example.com/scrape
~http://example.com/x/announce -> ~http://example.com/x/scrape
~http://example.com/announce.php -> ~http://example.com/scrape.php
~http://example.com/a -> (scrape not supported)
~http://example.com/announce?x2%0644 -> ~http://example.com/scrape?x2%0644
~http://example.com/announce?x=2/4 -> (scrape not supported)
~http://example.com/x%064announce -> (scrape not supported)
scrape URL可以作為可選參數(shù)info_hash(上文描述的一個(gè)20字節(jié)值)的一個(gè)補(bǔ)充。但是這樣限制了Tracker向那個(gè)特殊的torrent發(fā)送報(bào)告。否則tracker正在管理的所有torrent的統(tǒng)計(jì)數(shù)據(jù)將會(huì)返回。強(qiáng)烈建議軟件編寫者盡可能使用info_hash參數(shù),這樣就能夠減少Tracker的負(fù)載和帶寬。
你也可以指定多個(gè)info_hash參數(shù)給Tracker (得支持多個(gè)info_hash參數(shù))。這不是官方規(guī)范的一部分,但是已經(jīng)成為了實(shí)際標(biāo)準(zhǔn),例如:
http://example.com/scrape.php?info_hash=aaaaaaaaaaaaaaaaaaaa&info_hash=bbbbbbbbbbbbbbbbbbbb&info_hash=cccccccccccccccccccc
這個(gè)HTTP GET方法的響應(yīng)是一個(gè)’text/plain’或者有時(shí)候是用gzip壓縮的文本,這個(gè)文本由一個(gè)B編碼的dictionary組成,這個(gè)dictionary包含如下的鍵(key):
l files:這是一個(gè)B編碼的dictionary,在該dictionary中,每一個(gè)torrent文件都有其相應(yīng)的鍵/值,這個(gè)鍵/值是相應(yīng)torrent文件的統(tǒng)計(jì)數(shù)據(jù)。每一個(gè)鍵(key)由20字節(jié)的二進(jìn)制info_hash組成。而該鍵所對(duì)應(yīng)的值也是dictionary,它包含如下的鍵(key):
n complete:完成文件下載的peer數(shù),即做種者的數(shù)量。(整數(shù)類型)
n downloaded:已向tracker注冊(cè)的下載完成的總次數(shù)("event=complete",即一個(gè)客戶端完成了下載) 。(整數(shù)類型)
n incomplete:非做種的peers數(shù)(還沒有完成該文件下載的peers數(shù)),即“占他人便宜者”。 (整數(shù)類型)
n name:(可選的),torrent的內(nèi)部名,由.torrent文件中info鍵所對(duì)應(yīng)值中的name指定。
注意這個(gè)響應(yīng)有三層dictionary嵌套。例如:
d5:filesd20:....................d8:completei5e10:downloadedi50e10:incompletei10eeee
表示....................是一個(gè)20字節(jié)的info_hash,有5個(gè)做種者,5個(gè)正在下載者以及50個(gè)已經(jīng)完成的下載。
Unofficial extensions to scrape(scrape的非正式擴(kuò)展)
下面的響應(yīng)鍵是非官方的。因?yàn)樗鼈兌际欠枪俜降,因此都是可選的。
l failure reason:可讀的錯(cuò)誤信息,這個(gè)信息告訴客戶端請(qǐng)求失敗的原因(字符串類型)。使用該鍵的知名客戶端:Azureus。
l flags:這是一個(gè)B編碼的dictionary,它包含多個(gè)標(biāo)志。flags鍵對(duì)應(yīng)的值是另一個(gè)嵌套的dictionary,可能包含如下鍵(key):
n min_request_interval:這個(gè)鍵所對(duì)應(yīng)的值是一個(gè)整數(shù),該整數(shù)指定兩個(gè)scraping操作之間的最小間隔秒數(shù)。發(fā)送該鍵(key)的知名Tracker是BNBT。使用該鍵(key)的知名客戶端是Azureus。