Fast Extension 協議擴展的開啟方式,需要在 BitTorrent 握手協議中設置一位特定的二進制位來開啟。在 BitTorrent 握手協議中的保留字節(reserved byte)的第三個最低有效位(third least significant bit)設置為 1,即將其與 0x04 進行按位或運算,來啟用 Fast Extension 。例如:
reserved[7] |= 0x04
如果連接的兩端都設置了這一位,那麼 Fast Extension 就會被啟用,並且可以使用其中的四個擴展功能:Have None/Have All 、 Reject Requests 、 Suggestions 和 Allowed Fast
。
需要注意的是,Fast Extension 只有在支持該協議擴展的兩個 BitTorrent 客戶端之間建立連接時才能生效。否則,即使設置了這一位,也無法啟用 Fast Extension 。
BitTorrent 協議中消息的語法指定所有整數都是四個字節的大端序,並且所有消息都以一個整數的消息長度開始。此外,它還指定除 Keep-Alive 外的所有消息將具有單個字節的操作碼和零個或多個依賴於操作碼的參數。聲明應按照 IETF RFC 2119 中所述的方式解釋某些關鍵詞(MUST 、 MUST NOT 、 REQUIRED 、 SHALL 、 SHALL NOT 、 SHOULD 、 SHOULD NOT 、 RECOMMENDED 、 MAY 和 OPTIONAL
)。這意味著這些單詞具有在 RFC 中定義的特定含義,它們用於指示對特定動作或行為的要求或建議水平。例如,“MUST” 表示必須遵循某項要求,“SHOULD” 則表示應該遵循某項建議,除非存在充分理由不這樣做。
現有消息語義的修改#
Fast Extension 對請求(Request)、阻塞(Choke)、取消阻塞(Unchoke)和取消請求(Cancel)消息的語義進行修改,並添加了一個拒絕請求(Reject Request)消息。現在,每個請求都保證只會收到一個響應,即相應的拒絕或相應的 piece 消息。即使請求被取消,接收到取消請求的節點也應該發送相應的拒絕或相應的 piece :正在處理中的請求仍然允許完成。阻塞不再隱含地拒絕所有掛起的請求,從而消除了一些可能導致重複請求不必要的 piece 的競爭條件。此外,如果一個節點收到了從未請求的 piece ,那麼它必須關閉連接。
Have All/Have None#
*Have All*: <len=0x0001> <op=0x0E>
*Have None*: <len=0x0001><op=0x0F>
這兩種消息都包含一個長度為 1 字節的整數和一個操作碼,其中 "Have All" 的操作碼是 0x0E,"Have None" 的操作碼是 0x0F 。當存在這兩個消息時,它們會替換掉 “Have Bitfield” 消息。在握手之後,必須恰好出現一個 “Have All” 、"Have None" 或 "Have Bitfield" 中的一个。
“Have All” 和 “Have None” 是 BitTorrent 協議中的消息類型,表示發送方已經擁有所有或者沒有任何 piece 。當存在這兩個消息時,它們會替換掉 “Have Bitfield” 消息。在握手之後,必須恰好出現一個 “Have All” 、”Have None” 或 “Have Bitfield” 中的一个。
這些消息的目的是為了節省帶寬,並且避免沒有 piece 時不發送任何消息的特殊情況。當 Fast Extension 被禁用時,如果某個節點接收到 “Have All” 或 “Have None” 消息,則該節點必須關閉連接。
建議性 Piece#
*Suggest Piece*: <len=0x0005><op=0x0D><index>
“Suggest Piece“ 是一個建議性的消息,意味著” 您可能想要下載這個 piece” 。它的預期用途是為了在不降低吞吐量的情況下進行超級共享(super-seeding1),以避免重複下載,並使磁碟 I/O 受限的種子可以上傳連續或相同的數據塊,以避免過多的磁碟查找。在所有情況下,種子應該操作以在網絡中維護大致相等數量的每個塊的副本。
對於任何給定時間,節點可以發送多個”Suggest Piece” 消息。如果接收方收到多個”Suggest Piece” 消息,則可能會將其解釋為表示所有建議的塊都同樣適合下載。
當禁用 Fast Extension 時,如果一個節點收到了一个”Suggest Piece” 消息,則該節點必須關閉連接。
Reject Request 拒絕請求#
*Reject Request*: <len=0x000D><op=0x10><index><begin><length>
通過發送這個消息,Peer 可以告訴其他 Peer 自己無法提供所請求的數據塊。接收方在收到該消息後,會將相應的請求從隊列中刪除,並嘗試向其他 Peer 請求相同的數據塊。
Reject Request 用於通知請求方,它所請求的數據塊無法被滿足。
如果 Fast Extension 沒有啟用,且一個節點接收到了 Reject Request 消息,則該節點必須關閉與請求方之間的連接。
啟用 Fast Extension 時,節點在處理 Reject Request 消息時的規範行為:
- 如果一個節點接收到一個未曾發送請求的 Reject Request 消息,則它應該關閉與發出該消息的節點之間的連接。
- 當一個節點向另一個節點發送 Choke 消息時,它必須拒絕該節點發出的所有請求,除非這些請求涉及允許的快速集合中的數據塊。節點應該先 choke 再拒絕請求,這樣收到 Choke 消息的節點不會重新請求那些被 choke 的數據塊。
- 如果一個節點收到了來自被 choke 的節點的請求,則它會拒絕該請求,除非所請求的數據塊在允許的快速集合中。
- 如果一個節點收到了太多來自被 choke 的節點的請求,則它可以選擇關閉連接而不是拒絕這些請求。但是,要考慮到一旦一個節點被 choke,緩衝區可以需要幾秒鐘才能排空並且消息傳播才能完成。因此,需要在決定關閉連接之前仔細考慮這個問題。
Allowed Fast#
*Allowed Fast*: <len=0x0005><op=0x11><index>
使用指定的 BitTorrent 協議,新加入的節點由於缺少數據片段,需要等待一段時間才能與其他節點進行有效的文件共享。在這個過程中,節點可能會不斷地被 choke(阻止上傳),導致共享效率降低。
為了解決這個問題,BitTorrent 協議中引入了 “Allowed Fast” 消息。這個消息告訴其他節點,即使自己處於 choke 狀態,也可以向它請求某些數據片段,並保證會立即響應。這樣,其他節點就可以更快地獲取到需要的數據,而新加入節點也可以更快地開始參與 tit-for-tat 的交換過程,從而提高整個網絡的文件共享效率。
在這個協議中,當一個節點擁有某個文件的一部分時,它可以把這些 piece 分享給其他節點。當其他節點需要下載這個文件時,它們可以從那個節點處請求這些 piece,以便更快地完成文件的下載。
而 “Allowed Fast 集合” 則是指每個節點所允許請求的一組 piece 的集合。為了保證所有節點之間的數據請求都是公平的,在協議中使用了一個經過驗證的生成算法來生成這個集合。這個算法會為每個接收消息的節點生成唯一的 piece 索引,使得當兩個節點都提供了 k 個 piece 時,它們所能夠請求的 piece 的數量也是相同的;如果其中一個節點提供了 k+1 個 piece,則請求數量也會相應增加一。 k 的值應該足夠小以避免濫用,但又足夠大以實現 “以牙還牙” 的策略。作者目前將 k 的默認值設置為 10,但節點可以自由更改這個數字,以適應不同的負載情況。
發送方可以在 Allowed Fast 消息中列出它還沒有實際擁有的 pieces ,接收方不能根據 Allowed Fast 消息認為發送方確實擁有這些 pieces 。這樣做的目的是為了允許節點在連接開始時生成和通信允許快速集合。然而,發送方隨時都可以發送 Allowed Fast 消息。
一個節點如果有足夠的資源,應該向任何一個起始節點發送 Allowed Fast 消息,以提高其他節點下載文件分塊的速度。但是,在某些情況下,節點可以拒絕已經發送了 Allowed Fast pieces 的請求,例如本地節點資源不足、請求的 pieces 已經發送給請求的節點、或者請求節點並非一個起始節點。此外,當前實現的規則還規定了一種情況,即當請求節點已經下載了超過 k 個 pieces 時,請求被拒絕。
當 Fast 擴展被禁用時,只要節點收到了 Allowed Fast 消息,它就沒有能力處理這種消息,因此必須斷開與發送方的連接。這個規則的目的是確保協議的兼容性和正確性,保證所有節點都能夠按照相同的規則進行通信,從而實現文件分塊的有效下載和傳輸。
Allowed Fast Set 機制#
計算對等節點的快速列表的標準算法中所有的整數都是四個字節(32 位)的網絡字節序(大端序)。 [a] 表示從 a 到 b 的連續字節序列,不包括 b,即 (a, a+1, a+2,…, b-1) 。 x [a] 表示數組 x 中從索引 a 開始到索引 b(但不包括 b)的子序列。
計算網絡地址的方法。其中,“ip” 代表 P’*s IPv4 地址。該方法目前不支持 IPv6 地址。如果對等方在 NAT 後面,則 “ip” 應為 NAT 的外部 IP 地址。由於發送 “Allowed Fast” 消息的節點計算集合,因此通常正確的 “ip” 是連接另一端的 “ip” 地址。計算集合的主機可以根據需要使用連接另一端的 “ip” 地址。簡而言之,這意味著,在計算集合時,可以選擇使用連接另一端的 IP 地址作為計算中的 IP 地址,而不一定是自己的 IP 地址。
用 “sz” 代表種子文件中分片的數量。而 “a” 代表允許快速下載的集合,該集合包含一些不在正常下載順序中的分片。最後,“k” 代表被允許以快速方式下載的分片數,即允許快速下載的集合中所包含的分片數目。
x = 0xFFFFFF00 & ip (1)
x.append(infohash) (2)
while |a| < k:
x = SHA1(x) (3)
for i in [0:5] and |a| < k: (4)
j = i*4 (5)
y = x[j:j+4] (6)
index = y % sz (7)
if index not in a: (8)
add index to a (9)
第一步(1)選擇節點 P’*s 的 IP 地址中最重要的八位字節。這樣可以防止同一個網絡上的用戶獲得多個 Allowed Fast Set 。使用三個字節是基於經驗和歷史原因的。
第三步(3)在每個調用上生成一個 20 字節的隨機數。通過對前一次迭代的哈希執行 SHA-1 哈希,我們可以生成任意長度的偽隨機序列。
步驟(4)到(9)將 20 字節哈希劃分為若干片段索引,並將其添加到允許快速集合中。簡單來說,該過程將隨機數分成了 5 個 4 字節的片段,並將每個片段作為指向表示內容不同部分的索引集合中的一個索引。如果該索引尚未被添加到允許快速集合中,則將其添加到集合中。這確保只有擁有特定索引的一部分節點才能被選入 “允許快速” 節點集合。
Example Implementation 示例實現#
以下的 C++ 實現由 CacheLogic 提供
void generate_fast_set(
uint32 k, // number of pieces in set
uint32 sz, // number of pieces in torrent
const char infohash[20], // infohash of torrent
uint32 ip, // in host byte order, ie localhost is 0x7f000001
std::
vector<uint32> &a) // generated set of piece indices
{
a.clear();
std::string x;
char buf[4];
*(uint32*)buf = htonl(ip & 0xffffff00);
x.assign(buf, 4);
x.append(infohash, 20); // (3)
while (a.size()<k) {
x = SHA1(x); // (4)
for ( int i=0 ; i<5 && a.size()<k; i++ ) { // (5)
int j = i*4; // (6)
uint32 y = ntohl(*(uint32*)(x.data()+j)); // (7)
uint32 index = y % sz; // (8)
if (std::find(a.begin(), a.end(), index)==a.end()) { // (9)
a.push_back(index); // (10)
}
}
}
}
此函數生成的示例結果:
7 piece allowed fast set for torrent with 1313 pieces and hex infohash
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa for node with IP 80.4.4.200:
1059,431,808,1217,287,376,1188
9 piece allowed fast set for torrent with 1313 pieces and hex infohash
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa for node with IP 80.4.4.200:
1059,431,808,1217,287,376,1188,353,508
總結#
BitTorrent 的 Fast Extension(簡稱 FAST)是一種加速下載的協議擴展,它能夠顯著提高文件下載速度。 FAST 利用了一些技術手段來優化下載過程,如多線程下載、數據塊預取和請求重排等。
具體地說,FAST 通過請求多個數據塊,並在這些數據塊到達之前對它們進行排序以減少延遲,從而使下載更快。此外,FAST 還利用多線程下載技術,同時從不同的上傳者處獲取數據塊,進一步提高下載速度。
需要注意的是,FAST 只適用於支持該協議擴展的 BitTorrent 客戶端之間的通信,因此如果你使用的客戶端不支持 FAST,那麼即使有其他客戶端支持該協議擴展,也無法加速你的下載。