【P2P網絡】BitTorrent協議中文版4

Peer wire protocol (TCP)
概述
peer()協議使片(piece)的交換變得容易,片的描述請參考元信息文件。

注意:原來的規範在描述peer協議時,也使用術語piece“()”,但是這不同於元信息文件裏面的術語“piece()”,由於這個原因,在本規範中,將使用術語(block)”來描述peers()之間交換的數據。

一個客戶端(client)必須維持其與每一個遠程peer()連接的狀態信息:

l  choked: 遠程peer()是否已經choke本客戶端。當一個peer() choke本客戶端後,它是在通知本客戶端,除非它unchoke本客戶端,否則它不會應答該客戶端所發出的任何請求。本客戶端也不應該試圖向遠程peer發送數據請求,並且應該認爲所有沒有應答的請求已經被遠程peer丟棄。

l  interested: 遠程peer()是否對本客戶端提供的數據感興趣。這是遠程peer在通知本客戶端,當本客戶端unchoke他們時,遠程客戶端將開始請求塊(block)

注意這也意味着本客戶端需要記錄它是否對遠程peer()感興趣,以及它是否choke/unchoke遠程peer。因此真正的列表看起來像這樣:

l  am_choking: 本客戶端正在choke遠程peer

l  am_interested: 本客戶端對遠程peer感興趣。

l  peer_choking: 遠程peerchoke本客戶端。

l  peer_interested: 遠程peer對本客戶端感興趣。

客戶端連接開始時狀態是chokenot interested(不感興趣)。換句話就是:

l  am_choking = 1

l  am_interested = 0

l  peer_choking = 1

l  peer_interested = 0

當一個客戶端對一個遠程peer感興趣並且那個遠程peer沒有choke這個客戶端,那麼這個客戶端就可以從遠程peer下載塊(block)。當一個客戶端沒有choke一個peer,並且那個peer對這個客戶端這個感興趣時,這個客戶端就會上傳塊(block)

客戶端必須不斷通知它的peers,它是否對它們感興趣,這一點是很重要的。客戶端和每個端的狀態信息必須保持最新,即使本客戶端被choke。這允許所有的peer知道,當它們unchoke該客戶端後,該客戶端是否開始下載(反之亦然)

數據類型
如果沒有用其他的方法指定,在peer wire協議中的所有整數都會編碼爲4個字節的大端(big-endian)值。這也包括在握手之後,所有報文(Message)的長度前綴。

報文流(Message flow)
(譯者注:因爲ICMP-Internet控制報文協議中的Message翻譯成報文,同時IP/TCP層中傳輸的數據都翻譯爲數據報,應用層傳輸的數據都翻譯成報文,因此在這裏Message翻譯成報文)

peer wire協議由一個初始的握手組成。握手之後,peers通過以長度爲前綴消息的交換進行通信。長度前綴就是上面描述的整數。

握手(HandShake)
握手是一個必需的報文,並且必須是客戶端發送的第一個報文。該握手報文的長度是(49+len(pstr))字節。

握手:handshake: <pstrlen><pstr><reserved><info_hash><peer_id>

l  pstrlen: <pstr>的字符串長度,單個字節。

l  pstr: 協議的標識符,字符串類型。

l  reserved: 8個保留字節。當前的所有實現都使用全0.這些字節裏面的每一個字節都可以用來改變協議的行爲。來自Bram的郵件建議應該首先使用後面的位,以便可以使用前面的位來改變後面位的意義。

l  info_hash: 元信息文件中info(key)對應值的20字節SHA1哈希。這個info_hash和在tracker請求中info_hash是同一個。

l  peer_id: 用於唯一標識客戶端的20字節字符串。這個peer_id通常跟在tracker請求中傳送的peer_id相同(但也不盡然,例如在Azureus,就有一個匿名選項)

BitTorrent協議1.0版本,pstrlen = 19, pstr = “BitTorrent protocol”

連接的發起者應該立即發送握手報文。如果接收方能夠同時地服務多個torrent,它會等待發起者的握手報文(torrentinfohash唯一標識)。儘管如此,一旦接收方看到握手報文中的info_hash部分,接收方必須儘快響應。trackerNAT-checking特性不會發送握手報文的peer_id字段。

如果一個客戶端接收到一個握手報文,並且該客戶端沒有服務這個報文的info_hash,那麼該客戶端必須丟棄該連接。

如果一個連接發起者接收到一個握手報文,並且該報文中peer_id與期望的peer_id不匹配,那麼連接發起者應該丟棄該連接。注意發起者可能接收來自trackerpeer信息,該信息包含peer註冊的peer_id。來自於trackerpeer_id需要匹配握手報文中的peer_id

peer_id
peer_id20個字節。至於怎麼將客戶端和客戶端版本信息編碼成peer_id,現在主要有兩種慣例:Azureus風格和Shadow風格。

Azureus風格使用如下編碼方式:’-’, 緊接着是2個字符的client id,再接着是4個數字的版本號,’-’,後面跟着隨機數。

例如:'-AZ2060-'...

使用這種編碼風格的知名客戶端是:

l  'AG' - Ares

l  'A~' - Ares

l  'AR' - Arctic

l  'AT' - Artemis

l  'AX' - BitPump

l  'AZ' - Azureus

l  'BB' - BitBuddy

l  'BC' - BitComet

l  'BF' - Bitflu

l  'BG' - BTG (uses Rasterbar libtorrent)

l  'BP' - BitTorrent Pro (Azureus + spyware)

l  'BR' - BitRocket

l  'BS' - BTSlave

l  'BW' - BitWombat

l  'BX' - ~Bittorrent X

l  'CD' - Enhanced CTorrent

l  'CT' - CTorrent

l  'DE' - DelugeTorrent

l  'DP' - Propagate Data Client

l  'EB' - EBit

l  'ES' - electric sheep

l  'FC' - FileCroc

l  'FT' - FoxTorrent

l  'GS' - GSTorrent

l  'HL' - Halite

l  'HN' - Hydranode

l  'KG' - KGet

l  'KT' - KTorrent

l  'LC' - LeechCraft

l  'LH' - LH-ABC

l  'LP' - Lphant

l  'LT' - libtorrent

l  'lt' - libTorrent

l  'LW' - LimeWire

l  'MO' - MonoTorrent

l  'MP' - MooPolice

l  'MR' - Miro

l  'MT' - MoonlightTorrent

l  'NX' - Net Transport

l  'OT' - OmegaTorrent

l  'PD' - Pando

l  'qB' - qBittorrent

l  'QD' - QQDownload

l  'QT' - Qt 4 Torrent example

l  'RT' - Retriever

l  'RZ' - RezTorrent

l  'S~' - Shareaza alpha/beta

l  'SB' - ~Swiftbit

l  'SS' - SwarmScope

l  'ST' - SymTorrent

l  'st' - sharktorrent

l  'SZ' - Shareaza

l  'TN' - TorrentDotNET

l  'TR' - Transmission

l  'TS' - Torrentstorm

l  'TT' - TuoTu

l  'UL' - uLeecher!

l  'UM' - µTorrent for Mac

l  'UT' - µTorrent

l  'VG' - Vagaa

l  'WT' - BitLet

l  'WY' - FireTorrent

l  'XL' - Xunlei

l  'XT' - XanTorrent

l  'XX' - Xtorrent

l  'ZT' - ZipTorrent

另外還需要識別的客戶端有:

l  'BD' (例如: -BD0300-)

l  'NP' (例如: -NP0201-)

l  'SD' (例如: -SD0100-)

l  'wF' (例如: -wF2200-)

l  'hk' (例如: -hk0010-) 中國IP地址,IP address, unrequestedly sends info dict in message 0xA, reconnects immediately after being disconnected, reserved bytes = 01,01,01,01,00,00,02,01

Shadow風格使用如下編碼方式:一個用於客戶端標識的ASCII字母數字,多達五個字符的版本號(如果少於5個,則以’-’填充),緊接着是3個字符(通常是’---’,但也不總是這樣),最後跟着隨機數。版本字符串中的每一個字符表示一個063的數字。'0'=0, ..., '9'=9, 'A'=10, ..., 'Z'=35, 'a'=36, ..., 'z'=61, '.'=62, '-'=63

你可以在這找到關於shadow編碼風格(包含關於版本字符串後的三個字符用法的習慣)的詳細說明。

例如:用於Shadow 5.8.11’S58B-----‘...

使用這種編碼風格的知名客戶端是:

l  'A' - ABC

l  'O' - Osprey Permaseed

l  'Q' - BTQueue

l  'R' - Tribler

l  'S' - Shadow's client

l  'T' - BitTornado

l  'U' - UPnP NAT Bit Torrent

Bram的客戶端現在使用這種風格:'M3-4-2--' or 'M4-20-8-'

BitComet使用不同的編碼風格。它的peer_id4ASCII字符’exbc’組成,接着是2個字節的xy,最後是隨機字符。版本號中的x在小數點前面,y是版本號後的兩個數字。BitLord使用相同的方案,但是在版本號後面添加’LORD’BitComet的一個非正式補丁曾經使用’FUTB’代替’exbc’。自版本0.59開始,BitComet peer id的編碼使用Azureus風格。

XBT客戶端也使用其特有的風格。它的peer_id由三個大寫字母’XBT’以及緊隨其後的代表版本號的三個ASCII數字組成。如果客戶端是debug版本,第七個字節是小寫字符’d’,否則就是’-‘。接着就是’-‘,然後是隨機數,大寫和小寫字母。例如:peer_id的開始部分爲'XBT054d-'表明該客戶端是版本號爲0.5.4debug版本。

Opera 8預覽版和Opera 9.x發行版使用以下的peer_id方案:開始的兩個字符是’OP’,後面的四個數字是開發代號。接着的字符是隨機的小寫十六進制數字。

MLdonkey使用如下的peer_id方案:開始的字符是’-ML’,後面跟着點式版本,然後就是一個’-’,最後跟着隨機字符串。例如:'-ML2.7.2-kgjjfkd'

Bit on Wheels使用模式'-BOWxxx-yyyyyyyyyyyy',其中y是隨機的(大寫字母)x依賴於版本。如果版本爲1.0.6,那麼xxx = AOC

Queen Bee使用Bram的新風格:'Q1-0-0--' or 'Q1-10-0-'之後緊隨着隨機字節。

BitTyrantAzureus的一個分支,在它的1.1版本,其peer id使用'AZ2500BT' + 隨機字節的方式。

TorrenTopia版本1.90自稱是或源自於Mainline 3.4.6。它的peer ID'346------'開始。

BitSpirit有幾種編碼peer ID的方式。一種模式是讀取它的peer ID然後使用開始的八個字節作爲它peer ID的基礎來重新連接。它的實際ID使用'\0\3BS'(c 標記法)作爲版本3.x的前四個字節,使用'\0\2BS'作爲版本2.x的前四個字節。所有方式都使用'UDP0'作爲結尾。

Rufus使用它的十進制ASCII版本值作爲開始的兩個字節。第三個和第四個字節是'RS'。緊隨其後的是用戶的暱稱和一些隨機字節。

C3 Torrentpeer ID’-G3’開始,然後追加多達9個表示用戶暱稱的字符。

FlashGet使用Azureus風格,但是前面字符是’FG’,沒有’-’。版本 1.82.1002 仍然使用版本數字 '0180'

BT Next Evolution源自於BitTornado,但是試着模仿Azureus風格。結果是它的peer ID’-NE’開始,接着是四個數字的版本號,最後就是以shadow peer id風格描述客戶端類型的三個字符。

AllPeers takes the sha1 hash of a user dependent string(這個不好翻譯,待譯),使用"AP" + version string + "-"代替開始的一些字符。

Qvodid以四個字母"QVOD"開始,接着是4個十進制數字的開發代號(目前是” 0054”)。最後的12個字符是隨機的大寫十六進制數字。中國有一個修改版,該版本以隨機字節代替前四個字符。

許多客戶端全部使用隨機數或者隨機數後面跟12個全0(Bram客戶端的老版本)

報文(Messages)
接下來協議的所有報文采用如下的結構:<length prefix><message ID><payload>length prefix(長度前綴)是一個4字節的大端(big-endian)值。message ID是單個十進制值。playload與消息相關。

l  keep-alive: <len=0000>

keep-alive消息是一個0字節的消息,將length prefix設置成0。沒有message IDpayload。如果peers在一個固定時間段內沒有收到任何報文(keep-alive或其他任何報文),那麼peers應該關掉這個連接,因此如果在一個給定的時間內沒有發出任何命令的話,peers必鬚髮送一個keep-alive報文保持這個連接激活。通常情況下,這個時間是2分鐘。

l  choke: <len=0001><id=0>

choke報文長度固定,並且沒有payload

l  unchoke: <len=0001><id=1>

unchoke報文長度固定,並且沒有payload

l  interested: <len=0001><id=2>

interested報文長度固定,並且沒有payload

l  not interested: <len=0001><id=3>

not interested報文長度固定,並且沒有payload

l  have: <len=0005><id=4><piece index>

have報文長度固定。payloadpiece()的從零開始的索引,該片已經成功下載並且通過hash校驗。

實現者注意:實際上,一些客戶端必須嚴格實現該定義。因爲peers不太可能下載他們已經擁有的piece(),一個peer不應該通知另一個peer它擁有一個piece(),如果另一個peer擁有這個piece()。最低限度”HAVE suppresion”會使用have報文數量減半,總的來說,大致減少25-35%HAVE報文。同時,給一個擁有piece()peer發送HAVE報文是值得的,因爲這有助於決定哪個piece是稀缺的。

一個惡意的peer可能向其他的peer廣播它們不可能下載的piece()Due to this attempting to model peers using this information is a bad idea.

l  bitfield: <len=0001+X><id=5><bitfield>

bitfield報文可能僅在握手序列發送之後,其他消息發送之前立即發送。它是可選的,如果一個客戶端沒有piece(),就不需要發送該報文。

bitfield報文長度可變,其中xbitfield的長度。payload是一個bitfield,該bitfield表示已經成功下載的piece()。第一個字節的高位相當於piece索引0。設置爲0的位表示一個沒有的piece,設置爲1的位表示有效的和可用的piece。末尾的冗餘位設置爲0

長度不對的bitfield將被認爲是一個錯誤。如果客戶端接收到長度不對的bitfield或者bitfield有任一冗餘位集,它應該丟棄這個連接。

l  request: <len=0013><id=6><index><begin><length>

request報文長度固定,用於請求一個塊(block)payload包含如下信息:

n  index: 整數,指定從零開始的piece索引。

n  begin: 整數,指定piece中從零開始的字節偏移。

n  length: 整數,指定請求的長度。

l  piece: <len=0009+X><id=7><index><begin><block>

piece報文長度可變,其中x是塊的長度。payload包含如下信息:

n  index: 整數,指定從零開始的piece索引。

n  begin: 整數,指定piece中從零開始的字節偏移。

n  block: 數據塊,它是由索引指定的piece的子集。

l  cancel: <len=0013><id<=8><index><begin><length>

cancel報文長度固定,用於取消塊請求。playloadrequest報文的playload相同。一般情況下用於結束下載。

l  port: <len=0003><id=9><listen-port>

port報文由新版本的Mainline發送,新版本Mainline實現了一個DHT tracker。該監聽端口是peer的DHT節點正在監聽的端口。這個peer應該插入本地路由表(如果支持DHT tracker的話)。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章