bt協議詳解 基礎篇(下)
最近開發了一個免費教程的網站,產生了仔細了解bt協議的想法,所以寫了這一篇文章,后續還會寫一些關於搜索和索引的東西,都是在開發這個網站的過程中學習到的技術,敬請期待。
1 簡介
bt是BitTorrent協議的簡稱,bt協議是最流行的p2p下載協議,另外一種比較流行的p2p下載協議叫ed2k,ed2k的全稱叫eDonkey2000 network,這里我們只討論bt協議,ed2k協議以后有機會再和大家分享。
相信很多人都聽說過bt協議。但是當我問周圍的人究竟什么是bt協議呢?他們的解釋讓我對bt協議的理解變得更含糊,為了弄清楚心中的問題,我開始了自己對bt協議的學習。
我在官網 上找到一篇文章The BitTorrent Protocol Specification。這個標題翻譯過來就是“bittorrent協議規范”,是bittorrent協議的基礎篇,為什么說是基礎篇呢?
BT協議是一個協議簇。
有點像tcp/ip協議一樣,bt協議不是一個簡單的協議,而是一系列相關的協議組成的,而且這個協議簇一直在進化。
既然這篇文章的主題是“基礎篇”,所以它的內容主要來自bep_0003,也就是bittorrent協議規范,因為其它的協議都是以這個協議為基礎的,可見這個的重要性。
接上篇。
peer protocol
bt peer協議是基於tcp或者utp協議(utp協議也是bt協議簇中的一個,后面會專門寫一篇關於utp協議的文章)。
peer連接是對稱的,雙方可以同時發送數據,而且數據的形式是一樣的。一個peer代表一個bt下載用戶。
peer協議會使用torrent文件中的pieces塊(文件塊,前面有講到),下標從0開始。當一個peer下載完一個文件塊,檢查文件塊的hash值匹配正確的時候,它就發送一個announce請求給擁有該piece塊的peer列表,聲明自己擁有該piece塊,這樣其它的peer就可以向這個peer發送下載該piece的請求。
peer鏈接兩端包含2位的狀態:choked,unchoked和interested,uninterested。Choking表示不會發送數據知道一個unchoking動作發生。后面將會解釋為什么會存在choking這個狀態。
當peer連接的雙方有一個是interested狀態,而且另外一個不是choking狀態,這個連接就可以進行數據傳輸。無論何時當一個下載者向一個unchoked狀態的peer發送下載請求時,interest狀態必須每次更新 。這個屬性的實現比較困難,但是這讓下載者知道當它是unchoked的狀態時哪些peers將會立刻開始下載成為可能。
peer連接一開始是choked和uninterested狀態。
當數據開始傳輸時下載者必須把下載塊放進請求隊列來獲取更高的tcp性能(這就是所謂的管道技術)。另一方面,不能馬上寫入tcp緩存的請求必須放進隊列,而不是放在應用層的網絡緩沖區,這樣當choke動作發生時,他們才能被丟掉。
peer連線協議由握手和緊跟着的無窮的用長度做前綴的字符串流。握手由19(十進制字符串)跟着字符串'BitTorrent protocol'開始。開始的字符串是長度。
后面所有的整數都是使用4字節big-endian(高字節序)
固定的頭部之后跟着是8個保留字節,在目實現的協議版本中值都是0。如果你想擴展協議,可以使用這8個字節,請和Bram Cohen(bt協議的作者)聯系確保所有擴展的兼容性。
再接下來是20個字節的sha1哈希值,來自torrent文件中的info字段。如果peer連接的兩端發送的哈希值不一致,則連接被關閉。一個例外的情形是當一個下載者想在一個端口開始多線程下載,他們等待進來的連接發送hash,如果這個hash在它的維護的列表里面,就把這個hash返回給另一端。
20字節hash的后面是20字節的peer id,這個id會發送給bt tracker服務器,而且會出現在bt tracker返回的peer列表里面。
上面就是一次握手所有的內容。接下來是可選一系類的長度做前綴的消息。長度為0表示keepalives(保持連接),被忽略。保持連接消息每兩分鍾發送一次。
peer messages
所有的非保持連接的消息由一個表示類型的字節開始。
類型列表如下:
- 0 - choke
- 1 - unchoke
- 2 - interested
- 3 - not interested
- 4 - have
- 5 - bitfield
- 6 - reques5t
- 7 - piece
- 8 - cancel
'choke', 'unchoke', 'interested', 和 'not interested' 這四個消息沒有消息體。
bitfield消息只作為第一個消息發送一次。它的消息體是一個bitfield數據類型(參考c語言),下載者發送過的塊的下標對應的位置1,其余的置0。下載者沒有任何內容的時候可以跳過bitfield消息。bitfield的第一個字節對應下標0 - 7,第二個對應 8 - 15,等等。多余的位置0。
have消息的消息體是一個數字,表示下載者最近下載完成和檢驗正確的文件塊的下標。
request消息包含index、begin、length三個字段。最后兩個是字節偏移。length通常是2的指數除非是文件的最后一塊。當前所有bt協議的實現版本中length的值是16kiB,關閉連接的request中length字段的值要大於16kiB。
cancel消息和request有一樣的消息體。用來取消下載某一個文件塊。
piece消息包含index、begin、piece字段。它們的值和request消息是相關的。
下載者通常用隨機的順序下載文件塊,這樣能提高效率。
choking發生的原因有幾個。一個是當一次發起過多的連接時tcp擁塞控制表現極差。另外choking可以讓peer連接的雙方使用 tit-for-tat-ish算法來保證下載速度的一致。
一個好的choking算法必須具備幾個好的特性。它應該能控制並發數量來獲取更高的tcp性能。它應該避免過快的choking和unchoking。最后它應該每過一段時間就嘗試空閑連接來找到更好的連接,這就是所謂的unchoking優化。
本文來自 免費教程網