BitTorrent 協(xié)議規(guī)范

BitTorrent 是一種用于分發(fā)文件的協(xié)議。它通過 URL 標(biāo)識內(nèi)容,并且旨在與 Web 網(wǎng)絡(luò)無縫集成。相對于簡單的 HTTP 下載,它的優(yōu)勢在于當(dāng)多個用戶同時下載同一個文件時,這些用戶之間可以互相上傳文件塊,多個用戶共同參與文件傳輸,而非依賴于單一的文件服務(wù)器。使得文件源能夠支持大量用戶同時下載而只對其自身的負載產(chǎn)生較小的影響。
BitTorrent 文件分發(fā)由以下實體組成:
一個普通的 Web 服務(wù)器
一個靜態(tài)的 metainfo 文件
一個 BitTorrent tracker
一個原始下載器
網(wǎng)絡(luò)瀏覽器
BT 下載客戶端
一個文件在最理想情況下能夠被許多最終用戶共享下載。
要開始服務(wù),主機要執(zhí)行以下步驟:
啟動一個 tracker(或者已經(jīng)運行一個)。
啟動一個普通的 Web 服務(wù)器,比如 Apache(或者已經(jīng)有一個運行中)。
在他們的 Web 服務(wù)器上將擴展名 .torrent 與 MIME 類型 application/x-bittorrent 相關(guān)聯(lián)(或者已經(jīng)這樣做了)。
使用要提供服務(wù)的完整文件和 tracker 的 URL 生成 metainfo(.torrent) 文件。
將 metainfo 文件放在 Web 服務(wù)器上。
從其他網(wǎng)頁鏈接到 metainfo(.torrent) 文件。
啟動一個已經(jīng)擁有完整源文件的下載器。
要開始下載,用戶執(zhí)行以下操作:
安裝 BitTorrent 客戶端。
上網(wǎng)沖浪。
打開 .torrent 文件的鏈接。
選擇在本地保存文件的位置,或選擇要繼續(xù)的部分下載。
等待下載完成。
退出下載客戶端(它會一直上傳直到收到退出指令)。
Bencode 編碼
Bencode 編碼用于將任意數(shù)據(jù)類型的值序列化(也稱為 “串行化”)為字節(jié)流,以便在網(wǎng)絡(luò)上傳輸或存儲在磁盤上。 Bencode 編碼支持字符串、整數(shù)、列表和字典四種基本數(shù)據(jù)類型。
對于字符串類型,采用長度前綴加冒號的方式表示,例如”spam” 會被編碼為 4:spam 。
對于整數(shù)類型,以字符”i” 開始,后面跟著十進制表示的整數(shù)和字符”e”,例如 3 被編碼為 i3e,-3 被編碼為 i-3e 。
對于列表類型,以字符”l” 開始,后面跟著列表中各個元素的 Bencode 編碼,最后以字符”e” 結(jié)束,例如 [‘spam’, ‘eggs’] 被編碼為 l4:spam4:eggse 。
對于字典類型,以字符”d” 開始,后面跟著按照 key 的 ASCII 碼排序的鍵值對的 B 編碼,最后以字符”e” 結(jié)束,例如 {‘cow’: ‘moo’, ‘spam’: ‘eggs’} 被編碼為 d3:cow3:moo4:spam4:eggse 。需要注意的是,所有字典類型的鍵必須是字符串,并且按照原始字符串的排序方式進行排序。
Bencode 編碼提供了一種簡單、緊湊、可讀性較強的數(shù)據(jù)序列化方案,適用于各種數(shù)據(jù)類型的序列化和反序列化操作。
Metainfo 文件
MetaInfo 文件(也稱為 .torrent 文件)是使用 bencoding 編碼的字典,包含以下鍵:
announce
Tracker 的 URL 地址。
info
這個鍵映射到一個字典中,其中包含下面描述的鍵。
在包含文本的 .torrent 文件中的所有字符串都必須使用 UTF-8 編碼。
info dictionary
BitTorrent 下載文件時所使用的元數(shù)據(jù)信息。它包含了多個鍵值對,其中每個鍵都代表了一個特定的屬性,例如建議保存的文件名、文件塊的大小和哈希值等。這些屬性可以幫助客戶端正確地下載并組裝文件。
其中一些重要的屬性包括:
name:建議保存的文件名,它純粹是為了提供建議而不具有強制性。
piece length:文件被分成固定大小的塊,該屬性指定每個塊的大?。ㄍǔJ?2 的冪次方)。
pieces:每個塊對應(yīng)的哈希值,用于驗證文件的完整性。
length:文件長度(只適用于單個文件的情況),或者所有文件拼接后的總長度。
如果下載的是單個文件,則只需要使用 name 和 length 屬性。如果是多個文件,則需要使用 files 列表來表示文件的目錄結(jié)構(gòu),其中每個文件都由一個字典表示,包含 length 和 path 屬性。
trackers
Tracker GET 請求包含以下關(guān)鍵字:
info_hash:元信息文件中 info 值的 bencoded 形式的 20 字節(jié) SHA1 哈希值。該值幾乎肯定需要進行轉(zhuǎn)義。請注意,這是元信息文件的子字符串。 info-hash 必須是 .torrent 文件中編碼形式的哈希值,這與對元信息文件進行 bencoded 解碼、提取 info 字典并編碼它完全相同,如果 bencoded 編碼完全驗證了輸入(例如,鍵排序、前導(dǎo)零的缺失),則必須這樣做。反之,這意味著客戶端必須拒絕無效的元信息文件或直接提取子字符串。不能對無效數(shù)據(jù)執(zhí)行解碼-編碼往返。
peer_id:長度為 20 的字符串,用作此下載器的 ID 。每個下載器在開始新下載時都會隨機生成自己的 ID 。該值也幾乎肯定需要進行轉(zhuǎn)義。
ip:可選參數(shù),指定此對等方所在的 IP 地址(或 DNS 名稱)。通常用于源地址,如果源位于與跟蹤器相同的計算機上,則使用此參數(shù)。
port:此對等方正在偵聽的端口號。常見行為是讓下載器嘗試偵聽端口 6881,并在該端口被占用時嘗試 6882 、 6883 等端口號,并在 6889 后放棄。
uploaded:到目前為止已上傳的總量,以十進制 ASCII 編碼。
downloaded:到目前為止已下載的總量,以十進制 ASCII 編碼。
left:此對等方仍需下載的字節(jié)數(shù),以十進制 ASCII 編碼。請注意,這不能從 downloaded 和文件長度計算出來,因為它可能是恢復(fù)下載,并且有可能一些已下載的數(shù)據(jù)未通過完整性檢查而需要重新下載。
event:這是一個可選關(guān)鍵字,映射到 started 、 completed 或 stopped(或空,與不存在相同)。如果不存在,則是定期通告之一。當(dāng)下載開始時,使用 started 發(fā)送一個通知;當(dāng)下載完成時,使用 completed 發(fā)送一個通知。如果在開始時文件已完成,則不發(fā)送 completed 。下載器停止下載時會使用 stopped 發(fā)送一個通告。
Tracker 響應(yīng)是 bencoded 字典。如果跟蹤器響應(yīng)具有 failure reason 關(guān)鍵字,則該關(guān)鍵字映射到人類可讀的字符串,用于解釋查詢失敗的原因,并且不需要其他關(guān)鍵字。否則,它必須具有兩個關(guān)鍵字:interval,其映射到下載器應(yīng)在定期重新請求之間等待的秒數(shù);并且 peers,其映射到對等方列表的字典,每個字典包含 peer id 、 ip 和 port 這三個關(guān)鍵字,分別表示對等方的自選擇 ID 、 IP 地址或 DNS 名稱以及端口號。請注意,如果發(fā)生事件或需要更多對等方,下載器可能在非定期時間上重新請求。
更常見的是,跟蹤器會返回對等方列表的壓縮表示形式,請參見 Tracker Returns Compact Peer Lists 。
如果您想對元信息文件或跟蹤器查詢進行任何擴展,請與 Bram Cohen 協(xié)調(diào),以確保所有擴展都是兼容的。
通常還可以通過 UDP 跟蹤器協(xié)議進行通告。
peer protocol
BitTorrent 的對等協(xié)議通過 TCP 或?uTorrent transport protocol?運行。在 BitTorrent 中,下載者和上傳者都是對等的,數(shù)據(jù)可以在它們之間相互流動。數(shù)據(jù)被分成許多小塊,從多個源同時下載,從而提高下載速度和傳輸?shù)目煽啃?。每?dāng)下載者完成一塊文件的下載,并檢查哈希值匹配時,它會向所有對等者廣播該塊的信息。
連接狀態(tài)有兩類:阻塞或未阻塞;感興趣或不感興趣。阻塞表示沒有數(shù)據(jù)將被發(fā)送,直到解除阻塞。數(shù)據(jù)傳輸只有在一方感興趣且另一方未阻塞的情況下才會發(fā)生。為了實現(xiàn)正確的數(shù)據(jù)傳輸,下載者必須保持感興趣的狀態(tài)并及時更新,盡管受到了阻塞。傳輸數(shù)據(jù)時,下載者應(yīng)保持多個塊的請求排隊以獲得良好的 TCP 性能,而請求不能立即寫入 TCP 緩沖區(qū)的請求則應(yīng)排隊在內(nèi)存中,以便在阻塞發(fā)生時全部丟棄。
對等協(xié)議由握手過程和永無止境的長度前綴消息組成。握手以十九(十進制)字符開頭,后面跟著字符串 “BitTorrent 協(xié)議” 。在連接兩個節(jié)點之前,它們需要進行握手以交換必要的信息。握手開始時,發(fā)送方會向接收方發(fā)送一個固定的握手消息,其中包括協(xié)議版本、保留字節(jié)、元數(shù)據(jù)哈希值和節(jié)點 ID 。接收方會驗證這些信息,并檢查它們是否與期望的值匹配。如果有任何不匹配,連接將斷開。握手成功后,雙方開始交換數(shù)據(jù)。數(shù)據(jù)是通過一系列長度前綴和消息來傳輸?shù)?。長度前綴表示該消息的長度,然后是實際的消息內(nèi)容。
peer messages
所有非激活消息都以單個字節(jié)開頭,下面給出了它們的類型。
可能的值為:
0 – choke?
1 – unchoke?
2 – interested?
3 – not interested?
4 – have?
5 – bitfield?
6 – request?
7 – piece?
8 – cancel?
‘choke’, ‘unchoke’, ‘interested’, and ‘not interested’ 沒有有效載荷。
bitfield 消息:該消息只會作為第一個消息被發(fā)送。它的負載是一個位域,每個下載器發(fā)送的索引都被設(shè)置為 1,其余索引則被設(shè)置為 0 。沒有任何數(shù)據(jù)的下載器可以跳過這個 “bitfield” 消息。位域的第一個字節(jié)對應(yīng)于索引 0-7(從高位到低位),接下來是 8-15,以此類推。結(jié)尾處的多余位被設(shè)置為 0 。
have 消息:該消息的負載是一個單一的數(shù)字,表示該下載器完成并檢查哈希值的索引。
request 消息:該消息包含一個索引、偏移量和長度。最后一個參數(shù)通常是 2 的冪次方,除非已經(jīng)到達文件的末尾。所有當(dāng)前的實現(xiàn)都使用 2^14(16 kiB),并關(guān)閉請求超出此限制的連接。
cancel 消息:與請求消息具有相同的有效負載。它們通常只在下載結(jié)束時發(fā)送,在所謂的 “終局模式” 期間。當(dāng)下載幾乎完成時,最后幾部分傾向于從單個軟管調(diào)制解調(diào)器線路下載,這需要很長時間。為了確保最后幾塊快速進入,一旦給定下載器尚未收到的所有部分的請求當(dāng)前處于待處理狀態(tài),它就會向正在下載的每個人發(fā)送所有內(nèi)容的請求。為了防止這變得非常低效,每次有一件作品到達時,它都會向其他人發(fā)送取消。
piece 消息:包含索引、開始和片段。請注意,它們與請求消息隱式關(guān)聯(lián)。如果快速連續(xù)發(fā)送阻塞和取消阻塞消息和/或傳輸速度非常慢,則可能會出現(xiàn)意外的片段。
首先,下載器通常會隨機下載文件的不同部分,從而避免出現(xiàn)某個下載器擁有其他下載器的子集或超集的情況。其次,為了保證每個下載器都能獲得一致的下載速度,需要進行限制上傳速度的操作(也稱作 choking)。這種算法能夠讓下載器之間使用類似于” 以牙還牙” 的策略,以保證自己能獲得穩(wěn)定的下載速度。最后,當(dāng)前已經(jīng)在使用的 choking 算法,并強調(diào)了新算法需要在不同網(wǎng)絡(luò)環(huán)境下都表現(xiàn)良好的重要性。
首先,為了保證良好的 TCP 性能,算法需要限制同時上傳的連接數(shù)。其次,為了避免頻繁地 choke 和 unchoke,算法需要穩(wěn)定地選擇上傳對象。此外,在一定程度上應(yīng)該回報那些讓自己下載的 peer 。最后,算法應(yīng)該嘗試利用未使用的連接來提高下載速度,這被稱作 optimistic unchoking 。
當(dāng)前部署的 choking 算法采取了一些措施來實現(xiàn)這些目標(biāo)。為了避免頻繁的變化,算法每 10 秒才會更改哪些 peer 被 choke 。為了回報其他人,并限制上傳連接數(shù)量,算法選擇前四個下載速率最好且有興趣的 peer 來 unchoke 。如果有其他 peer 的上傳速率更好但是沒有興趣,則該 peer 也可能會被 unchoke,如果它突然有了興趣,就會 choke 掉下載速率最差的 peer 。如果某個 downloader 已經(jīng)完整地下載了文件,則它將使用上傳速率而不是下載速率來決定 unchoke 哪些 peer 。
至于 optimistic unchoking,算法會每 30 秒輪流選擇一個 peer 進行 unchoke,無論其上傳速率如何(只要有興趣就算一個下載器)。在 rotation 中,新連接被三倍概率放在當(dāng)前 optimistic unchoke 的位置上,以便給它們足夠的機會上傳完整的數(shù)據(jù)塊。
參考鏈接
http://bittorrent.org/beps/bep_0003.html