BT客戶端實現 Peer協議設計

與peer創建tcp鏈接後,首先發送handshake消息進行握手python

handshake消息格式以下:多線程

一個字節0x19 + 一個字符串'BitTorrent protocol' + 8 byte 保留字節默認值爲0(draft中對保留字節有定義)異步

+ 種子文件中info 部分的sha1字,大小爲20個字節 + 20個本身的peer id(從tracker獲取到的peer信息大多沒有peerid,這個可使用本地的peer id)socket

若是handshake信息協商不上,tcp鏈接將被關閉。tcp

 

BT標準BEP-3中定義了8種peer消息:消息格式爲msg_len(4個字節) + msg_type(1一個字節) + payload函數

0 - choke  --發送該消息表示本段發送阻塞,對端將不能獲取到piece數據,payload 爲 0性能

1 - unchoke  --發送該消息表示解阻塞,對端能夠開始發送請求獲取piece數據,payload 爲 0線程

2 - interested  --發送該消息,表示對對端的pieces數據有興趣,payload 爲 0設計

3 - not interested  ---發送該消息,表示對對端的pieces數據沒有興趣了,payload 爲 0rest

4 - have       ---發送該消息,通告對端 本段擁有的pieces,payload爲4個字節的piece index

5 - bitfield  ---發送該消息,通告對端 本段擁有的pieces,爲bit map的方式表示每一個piece index在本端是否擁有。piece index所在bit位爲1,表示擁有。

                     該消息爲handshake成功後的第一個消息。

6 - request   ---piece請求消息,payload爲: index, begin, and length,都是4個字節表示,length通常實現爲0x8000, 最大不能超過0x20000。

7 - piece     ---piece  數據,payload爲: index, begin,data 

8 - cancel    ---發送該消息,表示本端取消了某個piece請求。payload爲:index, begin, and length

 

使用python的異步socket接口實現,爲了減小處理過程被socket阻塞,使用多個線程處理每一個peer。

每一個peer包括3個線程:request timeout timer ,socket send data thread, socket receive data thread,使用select 函數判斷socket是否可讀、可寫。

對socket讀寫操做時使用RLock進行保護,select阻塞進程時不加鎖,避免阻塞其餘線程。

發送數據數據時先寫一個隊列,而後經過set threading.Event 變量出發socket send data thread發送數據,保證發送數據的線程不阻塞

因爲 python沒有結束線程的接口,socket send data thread, socket receive data thread 須要依賴特殊變量的賦值,使socket處理進程結束。

使用同步調用來觸發下載過程運轉,儘可能不使用timer輪詢的方式,能夠下降cpu使用率並加快下載過程。

可是,多線程間的同步調用因爲鎖的存在,會致使性能降低並容易引入信號量死鎖的問題。須要仔細設計好多線程的運行軌跡避免死鎖。

draft BEP中定義的功能暫未實現,peer的上傳流控未實現,peer質量分級未實現。

相關文章
相關標籤/搜索