peer之间的通信协议
peer之間的通信協議
?peer之間的通信協議又稱為peer?wire?protocal,即peer連線協議,它是一個基于TCP協議的應用層協議。
?為了防止有的peer只下載不上傳,BitTorrent協議建議,客戶端只給那些向它提供最快下載速度的4個peer上傳數據。簡單地說就是誰向我提供下載,我也提供數據供它下載;誰不提供數據給我下載,我的數據也不會上傳給它。客戶端每隔一定時間,比如10秒,重新計算從各個peer處下載數據的速度,將下載速度最快的4個peer解除阻塞,允許這4個peer從客戶端下載數據,同時將其他peer阻塞。
?一個例外情況是,為了發現下載速度更快的peer,協議還建議,在任一時刻,客戶端保持一個優化非阻塞peer,即無論該peer是否提供數據給客戶端下載,客戶端都允許該peer從客戶端這里下載數據。由于客戶端向peer上傳數據,peer接著也允許客戶端從peer處下載數據,并且下載速度超過4個非阻塞peer中的一個。客戶端每隔一定的時間,如30秒,重新選擇優化非阻塞peer。
當客戶端與peer建立TCP連接后,客戶端必須維持的幾個狀態變量如下表所示。
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 客戶端必須維持的狀態變量
| 狀?態?變?量 | ? ? ? ? ? ? ? ? ? ? ? ? 含????義 |
| am_chocking | 該值若為1,表明客戶端將遠程peer阻塞。此時如果peer發送數據請求給客戶端,客戶端將不會理會。也就是說,一旦將peer阻塞,peer就無法從客戶端下載到數據;該值若為0,則剛好相反,即表明peer未被阻塞,允許peer從客戶端下載數據 |
| am_interested | 該值若為1,表明客戶端對遠程的peer感興趣。當peer擁有某個piece,而客戶端沒有,則客戶端對peer感興趣。該值若為0,則剛好相反,即表明客戶端對peer不感興趣,peer擁有的所有piece,客戶端都擁有 |
| peer_chocking | 該值若為1,表明peer將客戶端阻塞。此時,客戶端無法從peer處下載到數據。該值若為0,表明客戶端可以向peer發送數據請求,客戶端將進行響應 |
| peer_interested | 該值若為1,表明peer對客戶端感興趣。也即客戶端擁有某個piece,而peer沒有。該值若為0,表明peer對客戶端不感興趣 |
當客戶端與peer建立TCP連接后,客戶端將這幾個變量的值設置為。
am_chocking?=?1。
am_interested??=?0。
peer_chocking?=?1。
peer_interested?=?0。
當客戶端對peer感興趣且peer未將客戶端阻塞時,客戶端可以從peer處下載數據。當peer對客戶端感興趣,且客戶端未將peer阻塞時,客戶端向peer上傳數據。
除非另有說明,所有的整數型在本協議中被編碼為4字節值(高位在前低位在后),包括在握手之后所有信息的長度前綴。
客戶端與一個peer建立TCP連接后,首先向peer發送握手消息,peer收到握手消息后回應一個握手消息。
l握手消息是一個長度固定為68字節的消息。消息的格式如下:
<pstrlen><pstr><reserved><info_hash><peer_id>
消息格式中一些參數的含義如下表所示。
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 握手消息
| 參????數 | 含????義 |
| pstrlen | pstr的長度,該值固定為19 |
| pstr | BitTorrent協議的關鍵字,即“BitTorrent?protocol” |
| reserved | 占8字節,用于擴展BT協議,一般這8字節都設置為0。有些BT軟件對BT協議進行了某些擴展,因此可能看到有些peer發來的握手消息這8個字節不全為0,不過不必理會,這不會影響正常的通信 |
| info_hash | 與發往Tracker的GET請求中的info_hash為同一個值,長度固定為20字節 |
peer_id與發往Tracker的GET請求中的peer_id為同一個值,長度固定為20字節。一般從peer_id可以識別出BT軟件的類型,例如,某peer發來的握手消息中peer_id的前8個字節為“-AZ2060-”,則可以斷定對方使用的是Azureus;若為“-BCxxxx-”,x為數字,則對方使用的是BitComet。
對于除握手消息之外的其他所有消息,其一般的格式為:
<length prefix><message ID><payload>
length?prefix(長度前綴)占4個字節,指明message?ID和payload的長度和。message?ID(消息編號)占一字節,是一個10進制的整數,指明消息的編號。payload(負載),長度未定,是消息的內容。
lkeep_alive消息:
keep_alive消息的長度固定,為4字節,它沒有消息編號和負載。如果一段時間內客戶端與peer沒有交換任何消息,則與這個peer的連接將被關閉。keep_alive消息用于維持這個連接,通常如果2分鐘內沒有向peer發送任何消息,則發送一個keep_alive消息。
lchoke消息:
choke消息的長度固定,為5字節,消息長度占4個字節,消息編號占1個字節,沒有負載。該消息的功能是,發出該消息的peer將接收該消息的peer阻塞,暫時不允許其下載自己的數據。
lunchoke消息:<id=< span="" style="word-wrap: break-word;">1>
unchoke消息的長度固定,為5字節,消息長度占4個字節,消息編號占1個字節,沒有負載。客戶端每隔一定的時間,通常為10秒,計算一次各個peer的下載速度,如果某peer被解除阻塞,則發送unchoke消息。如果某個peer原先是解除阻塞的,而此次被阻塞,則發送choke消息。
linterested消息:
interested消息的長度固定,為5字節,消息長度占4個字節,消息編號占1個字節,沒有負載。當客戶端收到某peer的have消息時,如果發現peer擁有了客戶端沒有的piece,則發送interested消息告知該peer,客戶端對它感興趣。
lnot?interested消息:
not?interested消息的長度固定,為5字節,消息長度占4個字節,消息編號占1個字節,沒有負載。當客戶端下載了某個piece,如果發現客戶端擁有了這個piece后,某個peer擁有的所有piece,客戶端都擁有,則發送not?interested消息給該peer。
lhave消息:?
have消息的長度固定,為9字節,消息長度占4個字節,消息編號占1個字節,負載為4個字節。負載為一個整數,指明下標為index的piece,peer已經擁有。每當客戶端下載了一個piece,即將該piece的下標作為have消息的負載構造have消息,并把該消息發送給所有與客戶端建立連接的peer。
lbitfield消息:
bitfield消息的長度不固定,其中X是bitfield(即位圖)的長度。當客戶端與peer交換握手消息之后,就交換位圖。位圖中,每個piece占一位,若該位的值為1,則表明已經擁有該piece;為0則表明該piece尚未下載。具體而言,假定某共享文件共擁有801個piece,則位圖為101個字節,位圖的第一個字節的最高位指明第一個piece是否擁有,位圖的第一個字節的第二高位指明第二個piece是否擁有,依此類推。對于第801個piece,需要單獨一個字節,該字節的最高位指明第801個piece是否已被下載,其余的7位放棄不予使用。
lrequest消息:
request消息的長度固定,為17個字節,index是piece的索引,begin是piece內的偏移,length是請求peer發送的數據的長度。當客戶端收到某個peer發來的unchoke消息后,即構造request消息,向該peer發送數據請求。前面提到,peer之間交換數據是以slice(長度為16KB的塊)為單位的,因此request消息中length的值一般為16K。對于一個256KB的piece,客戶端分16次下載,每次下載一個16K的slice。
lpiece消息:
piece消息是另外一個長度不固定的消息,長度前綴中的9是id、index、begin的長度總和,index和begin固定為4字節,X為block的長度,一般為16K。因此對于piece消息,長度前綴加上id通常為00?00?40?09?07。當客戶端收到某個peer的request消息后,如果判定當前未將該peer阻塞,且peer請求的slice,客戶端已經下載,則發送piece消息將文件數據上傳給該peer。
lcancel消息:<id<=8 style="word-wrap: break-word;">
cancel消息的長度固定,為17個字節,len、index、begin、length都占4字節。它與request消息對應,作用剛好相反,用于取消對某個slice的數據請求。如果客戶端發現,某個piece中的slice,客戶端已經下載,而客戶端又向其他peer發送了對該slice的請求,則向該peer發送cancel消息,以取消對該slice的請求。事實上,如果算法設計合理,基本不用發送cancel消息,只在某些特殊的情況下才需要發送cancel消息。
lport消息:
port消息的長度固定,為7字節,其中listen-port占兩個字節。該消息只在支持DHT的客戶端中才會使用,用于指明DHT監聽的端口號,一般不必理會,收到該消息時,直接丟棄即可。
總結
以上是生活随笔為你收集整理的peer之间的通信协议的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: VMTools安装
- 下一篇: 建议118:使用SecureString