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

BitTorrent 是一種用于分發(fā)文件的協(xié)議。它通過 URL 標(biāo)識(shí)內(nèi)容,并且旨在與 Web 網(wǎng)絡(luò)無縫集成。相對(duì)于簡(jiǎn)單的 HTTP 下載,它的優(yōu)勢(shì)在于當(dāng)多個(gè)用戶同時(shí)下載同一個(gè)文件時(shí),這些用戶之間可以互相上傳文件塊,多個(gè)用戶共同參與文件傳輸,而非依賴于單一的文件服務(wù)器。使得文件源能夠支持大量用戶同時(shí)下載而只對(duì)其自身的負(fù)載產(chǎn)生較小的影響。

BitTorrent 文件分發(fā)由以下實(shí)體組成:

  • 一個(gè)普通的 Web 服務(wù)器

  • 一個(gè)靜態(tài)的 metainfo 文件

  • 一個(gè) BitTorrent tracker

  • 一個(gè)原始下載器

  • 網(wǎng)絡(luò)瀏覽器

  • BT 下載客戶端

  • 一個(gè)文件在最理想情況下能夠被許多最終用戶共享下載。

要開始服務(wù),主機(jī)要執(zhí)行以下步驟:

  1. 啟動(dòng)一個(gè) tracker(或者已經(jīng)運(yùn)行一個(gè))。

  2. 啟動(dòng)一個(gè)普通的 Web 服務(wù)器,比如 Apache(或者已經(jīng)有一個(gè)運(yùn)行中)。

  3. 在他們的 Web 服務(wù)器上將擴(kuò)展名 .torrent 與 MIME 類型 application/x-bittorrent相關(guān)聯(lián)(或者已經(jīng)這樣做了)。

  4. 使用要提供服務(wù)的完整文件和 tracker 的 URL 生成 metainfo(.torrent) 文件。

  5. 將 metainfo 文件放在 Web 服務(wù)器上。

  6. 從其他網(wǎng)頁(yè)鏈接到 metainfo(.torrent) 文件。

  7. 啟動(dòng)一個(gè)已經(jīng)擁有完整源文件的下載器。

要開始下載,用戶執(zhí)行以下操作:

  1. 安裝 BitTorrent 客戶端。

  2. 上網(wǎng)沖浪。

  3. 打開 .torrent 文件的鏈接。

  4. 選擇在本地保存文件的位置,或選擇要繼續(xù)的部分下載。

  5. 等待下載完成。

  6. 退出下載客戶端(它會(huì)一直上傳直到收到退出指令)。

Bencode 編碼

Bencode 編碼用于將任意數(shù)據(jù)類型的值序列化(也稱為 “串行化”)為字節(jié)流,以便在網(wǎng)絡(luò)上傳輸或存儲(chǔ)在磁盤上。 Bencode 編碼支持字符串、整數(shù)、列表和字典四種基本數(shù)據(jù)類型。

  • 對(duì)于字符串類型,采用長(zhǎng)度前綴加冒號(hào)的方式表示,例如”spam” 會(huì)被編碼為 4:spam 。

  • 對(duì)于整數(shù)類型,以字符”i” 開始,后面跟著十進(jìn)制表示的整數(shù)和字符”e”,例如 3 被編碼為 i3e,-3 被編碼為 i-3e 。

  • 對(duì)于列表類型,以字符”l” 開始,后面跟著列表中各個(gè)元素的 Bencode 編碼,最后以字符”e” 結(jié)束,例如 [‘spam’, ‘eggs’] 被編碼為 l4:spam4:eggse 。

  • 對(duì)于字典類型,以字符”d” 開始,后面跟著按照 key 的 ASCII 碼排序的鍵值對(duì)的 B 編碼,最后以字符”e” 結(jié)束,例如 {‘cow’: ‘moo’, ‘spam’: ‘eggs’} 被編碼為 d3:cow3:moo4:spam4:eggse 。需要注意的是,所有字典類型的鍵必須是字符串,并且按照原始字符串的排序方式進(jìn)行排序。

Bencode 編碼提供了一種簡(jiǎn)單、緊湊、可讀性較強(qiáng)的數(shù)據(jù)序列化方案,適用于各種數(shù)據(jù)類型的序列化和反序列化操作。

Metainfo 文件

MetaInfo 文件(也稱為 .torrent 文件)是使用 bencoding 編碼的字典,包含以下鍵:

announce

Tracker 的 URL 地址。

info

這個(gè)鍵映射到一個(gè)字典中,其中包含下面描述的鍵。

在包含文本的 .torrent 文件中的所有字符串都必須使用 UTF-8 編碼。

info dictionary

BitTorrent 下載文件時(shí)所使用的元數(shù)據(jù)信息。它包含了多個(gè)鍵值對(duì),其中每個(gè)鍵都代表了一個(gè)特定的屬性,例如建議保存的文件名、文件塊的大小和哈希值等。這些屬性可以幫助客戶端正確地下載并組裝文件。

其中一些重要的屬性包括:

  • name:建議保存的文件名,它純粹是為了提供建議而不具有強(qiáng)制性。

  • piece length:文件被分成固定大小的塊,該屬性指定每個(gè)塊的大?。ㄍǔJ?2 的冪次方)。

  • pieces:每個(gè)塊對(duì)應(yīng)的哈希值,用于驗(yàn)證文件的完整性。

  • length:文件長(zhǎng)度(只適用于單個(gè)文件的情況),或者所有文件拼接后的總長(zhǎng)度。

如果下載的是單個(gè)文件,則只需要使用 name 和 length 屬性。如果是多個(gè)文件,則需要使用 files 列表來表示文件的目錄結(jié)構(gòu),其中每個(gè)文件都由一個(gè)字典表示,包含 length 和 path 屬性。

trackers

Tracker GET 請(qǐng)求包含以下關(guān)鍵字:

info_hash:元信息文件中 info 值的 bencoded 形式的 20 字節(jié) SHA1 哈希值。該值幾乎肯定需要進(jìn)行轉(zhuǎn)義。請(qǐng)注意,這是元信息文件的子字符串。 info-hash 必須是 .torrent 文件中編碼形式的哈希值,這與對(duì)元信息文件進(jìn)行 bencoded 解碼、提取 info 字典并編碼它完全相同,如果 bencoded 編碼完全驗(yàn)證了輸入(例如,鍵排序、前導(dǎo)零的缺失),則必須這樣做。反之,這意味著客戶端必須拒絕無效的元信息文件或直接提取子字符串。不能對(duì)無效數(shù)據(jù)執(zhí)行解碼-編碼往返。

peer_id:長(zhǎng)度為 20 的字符串,用作此下載器的 ID 。每個(gè)下載器在開始新下載時(shí)都會(huì)隨機(jī)生成自己的 ID 。該值也幾乎肯定需要進(jìn)行轉(zhuǎn)義。

ip:可選參數(shù),指定此對(duì)等方所在的 IP 地址(或 DNS 名稱)。通常用于源地址,如果源位于與跟蹤器相同的計(jì)算機(jī)上,則使用此參數(shù)。

port:此對(duì)等方正在偵聽的端口號(hào)。常見行為是讓下載器嘗試偵聽端口 6881,并在該端口被占用時(shí)嘗試 6882 、 6883 等端口號(hào),并在 6889 后放棄。

uploaded:到目前為止已上傳的總量,以十進(jìn)制 ASCII 編碼。

downloaded:到目前為止已下載的總量,以十進(jìn)制 ASCII 編碼。

left:此對(duì)等方仍需下載的字節(jié)數(shù),以十進(jìn)制 ASCII 編碼。請(qǐng)注意,這不能從 downloaded 和文件長(zhǎng)度計(jì)算出來,因?yàn)樗赡苁腔謴?fù)下載,并且有可能一些已下載的數(shù)據(jù)未通過完整性檢查而需要重新下載。

event:這是一個(gè)可選關(guān)鍵字,映射到 started 、 completed 或 stopped(或空,與不存在相同)。如果不存在,則是定期通告之一。當(dāng)下載開始時(shí),使用 started 發(fā)送一個(gè)通知;當(dāng)下載完成時(shí),使用 completed 發(fā)送一個(gè)通知。如果在開始時(shí)文件已完成,則不發(fā)送 completed 。下載器停止下載時(shí)會(huì)使用 stopped 發(fā)送一個(gè)通告。

Tracker 響應(yīng)是 bencoded 字典。如果跟蹤器響應(yīng)具有 failure reason 關(guān)鍵字,則該關(guān)鍵字映射到人類可讀的字符串,用于解釋查詢失敗的原因,并且不需要其他關(guān)鍵字。否則,它必須具有兩個(gè)關(guān)鍵字:interval,其映射到下載器應(yīng)在定期重新請(qǐng)求之間等待的秒數(shù);并且 peers,其映射到對(duì)等方列表的字典,每個(gè)字典包含 peer id 、 ip 和 port 這三個(gè)關(guān)鍵字,分別表示對(duì)等方的自選擇 ID 、 IP 地址或 DNS 名稱以及端口號(hào)。請(qǐng)注意,如果發(fā)生事件或需要更多對(duì)等方,下載器可能在非定期時(shí)間上重新請(qǐng)求。

更常見的是,跟蹤器會(huì)返回對(duì)等方列表的壓縮表示形式,請(qǐng)參見 Tracker Returns Compact Peer Lists 。

如果您想對(duì)元信息文件或跟蹤器查詢進(jìn)行任何擴(kuò)展,請(qǐng)與 Bram Cohen 協(xié)調(diào),以確保所有擴(kuò)展都是兼容的。

通常還可以通過 UDP 跟蹤器協(xié)議進(jìn)行通告。

peer protocol

BitTorrent 的對(duì)等協(xié)議通過 TCP 或 uTorrent transport protocol 運(yùn)行。在 BitTorrent 中,下載者和上傳者都是對(duì)等的,數(shù)據(jù)可以在它們之間相互流動(dòng)。數(shù)據(jù)被分成許多小塊,從多個(gè)源同時(shí)下載,從而提高下載速度和傳輸?shù)目煽啃?。每?dāng)下載者完成一塊文件的下載,并檢查哈希值匹配時(shí),它會(huì)向所有對(duì)等者廣播該塊的信息。

連接狀態(tài)有兩類:阻塞或未阻塞;感興趣或不感興趣。阻塞表示沒有數(shù)據(jù)將被發(fā)送,直到解除阻塞。數(shù)據(jù)傳輸只有在一方感興趣且另一方未阻塞的情況下才會(huì)發(fā)生。為了實(shí)現(xiàn)正確的數(shù)據(jù)傳輸,下載者必須保持感興趣的狀態(tài)并及時(shí)更新,盡管受到了阻塞。傳輸數(shù)據(jù)時(shí),下載者應(yīng)保持多個(gè)塊的請(qǐng)求排隊(duì)以獲得良好的 TCP 性能,而請(qǐng)求不能立即寫入 TCP 緩沖區(qū)的請(qǐng)求則應(yīng)排隊(duì)在內(nèi)存中,以便在阻塞發(fā)生時(shí)全部丟棄。

對(duì)等協(xié)議由握手過程和永無止境的長(zhǎng)度前綴消息組成。握手以十九(十進(jìn)制)字符開頭,后面跟著字符串 “BitTorrent 協(xié)議” 。在連接兩個(gè)節(jié)點(diǎn)之前,它們需要進(jìn)行握手以交換必要的信息。握手開始時(shí),發(fā)送方會(huì)向接收方發(fā)送一個(gè)固定的握手消息,其中包括協(xié)議版本、保留字節(jié)、元數(shù)據(jù)哈希值和節(jié)點(diǎn) ID 。接收方會(huì)驗(yàn)證這些信息,并檢查它們是否與期望的值匹配。如果有任何不匹配,連接將斷開。握手成功后,雙方開始交換數(shù)據(jù)。數(shù)據(jù)是通過一系列長(zhǎng)度前綴和消息來傳輸?shù)?。長(zhǎng)度前綴表示該消息的長(zhǎng)度,然后是實(shí)際的消息內(nèi)容。

peer messages

所有非激活消息都以單個(gè)字節(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 消息:該消息只會(huì)作為第一個(gè)消息被發(fā)送。它的負(fù)載是一個(gè)位域,每個(gè)下載器發(fā)送的索引都被設(shè)置為 1,其余索引則被設(shè)置為 0 。沒有任何數(shù)據(jù)的下載器可以跳過這個(gè) “bitfield” 消息。位域的第一個(gè)字節(jié)對(duì)應(yīng)于索引 0-7(從高位到低位),接下來是 8-15,以此類推。結(jié)尾處的多余位被設(shè)置為 0 。

have 消息:該消息的負(fù)載是一個(gè)單一的數(shù)字,表示該下載器完成并檢查哈希值的索引。

request 消息:該消息包含一個(gè)索引、偏移量和長(zhǎng)度。最后一個(gè)參數(shù)通常是 2 的冪次方,除非已經(jīng)到達(dá)文件的末尾。所有當(dāng)前的實(shí)現(xiàn)都使用 2^14(16 kiB),并關(guān)閉請(qǐng)求超出此限制的連接。

cancel 消息:與請(qǐng)求消息具有相同的有效負(fù)載。它們通常只在下載結(jié)束時(shí)發(fā)送,在所謂的 “終局模式” 期間。當(dāng)下載幾乎完成時(shí),最后幾部分傾向于從單個(gè)軟管調(diào)制解調(diào)器線路下載,這需要很長(zhǎng)時(shí)間。為了確保最后幾塊快速進(jìn)入,一旦給定下載器尚未收到的所有部分的請(qǐng)求當(dāng)前處于待處理狀態(tài),它就會(huì)向正在下載的每個(gè)人發(fā)送所有內(nèi)容的請(qǐng)求。為了防止這變得非常低效,每次有一件作品到達(dá)時(shí),它都會(huì)向其他人發(fā)送取消。

piece 消息:包含索引、開始和片段。請(qǐng)注意,它們與請(qǐng)求消息隱式關(guān)聯(lián)。如果快速連續(xù)發(fā)送阻塞和取消阻塞消息和/或傳輸速度非常慢,則可能會(huì)出現(xiàn)意外的片段。

首先,下載器通常會(huì)隨機(jī)下載文件的不同部分,從而避免出現(xiàn)某個(gè)下載器擁有其他下載器的子集或超集的情況。其次,為了保證每個(gè)下載器都能獲得一致的下載速度,需要進(jìn)行限制上傳速度的操作(也稱作 choking)。這種算法能夠讓下載器之間使用類似于” 以牙還牙” 的策略,以保證自己能獲得穩(wěn)定的下載速度。最后,當(dāng)前已經(jīng)在使用的 choking 算法,并強(qiáng)調(diào)了新算法需要在不同網(wǎng)絡(luò)環(huán)境下都表現(xiàn)良好的重要性。

首先,為了保證良好的 TCP 性能,算法需要限制同時(shí)上傳的連接數(shù)。其次,為了避免頻繁地 choke 和 unchoke,算法需要穩(wěn)定地選擇上傳對(duì)象。此外,在一定程度上應(yīng)該回報(bào)那些讓自己下載的 peer 。最后,算法應(yīng)該嘗試?yán)梦词褂玫倪B接來提高下載速度,這被稱作 optimistic unchoking 。

當(dāng)前部署的 choking 算法采取了一些措施來實(shí)現(xiàn)這些目標(biāo)。為了避免頻繁的變化,算法每 10 秒才會(huì)更改哪些 peer 被 choke 。為了回報(bào)其他人,并限制上傳連接數(shù)量,算法選擇前四個(gè)下載速率最好且有興趣的 peer 來 unchoke 。如果有其他 peer 的上傳速率更好但是沒有興趣,則該 peer 也可能會(huì)被 unchoke,如果它突然有了興趣,就會(huì) choke 掉下載速率最差的 peer 。如果某個(gè) downloader 已經(jīng)完整地下載了文件,則它將使用上傳速率而不是下載速率來決定 unchoke 哪些 peer 。

至于 optimistic unchoking,算法會(huì)每 30 秒輪流選擇一個(gè) peer 進(jìn)行 unchoke,無論其上傳速率如何(只要有興趣就算一個(gè)下載器)。在 rotation 中,新連接被三倍概率放在當(dāng)前 optimistic unchoke 的位置上,以便給它們足夠的機(jī)會(huì)上傳完整的數(shù)據(jù)塊。

參考鏈接

http://bittorrent.org/beps/bep_0003.html

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容