這一次又學了 Python 其實跟兩件事有關:Google App Engine 跟 BitTorrent,我就慢慢說明。
Google App Engine (GAE) 已經公開申請一段時間了,Google 提供各種資源讓你在上面開發網路應用程式,而且目前是免費的!只可惜支援的程式語言目前僅有 Python (因為 Python 之父 Guido van Rossum 在 Google 工作的關係吧)。雖然計畫未來會支援更多語言 (也許會有 Ruby, PHP, Java?) 但是在那一刻還沒到來之前,這麼爽的東西竟然因為我不會 Python 而不能痛快遊玩感到可惜。一方面前幾個月 Pixmicat! 開發討論版上面有個人做了一個 Python 版的移植 (雖然看起來是移植 futaba 祭典版),感覺很有趣,我想該是接觸新知識的時候了,於是就去下載了 GAE 的 SDK 和安裝 Python 環境。
看了一下 GAE 還是有些限制的,SDK 提供了一個範例,我看了一下似乎提供了一些整合 Framework,但是我連基本的都不會了,要我用什麼 Framework 呢?剛好又看到 GAEO 這個專門為 GAE 撰寫的 Framework,這還是台灣人 ericsk 主導的。當然要玩這些的大前提就是先會懂 Python。
另一個竟然是 BitTorrent,有沒有搞錯?沒搞錯,BitTorrent 原本就是使用 Python 開發的 (在還沒併購 μTorrent 之前,現在的已經是用 C++)。我記得以前有一個 TorrentSpy 軟體,可以幫助使用者在新增下載之前,先查看熱烈度 (Seeder/Leecher 人數),不然萬一早就沒人了豈不是白搭 (尤其是挖了很久以前的 torrent 檔更需要)。但是隨著時代的改變,BT 的通訊協定改變越來越大,2004 年後即停止開發的軟體早就跟不上時代,現在都已經支援多個 Tracker 查詢了,但是此軟體仍只能針對一組作查詢不太便利 (根據這篇修訂紀錄來看也是2008年才成為標準,不能怪他),目前好像也沒看到其他什麼可以取代的軟體,不如自己寫吧。
簡單了解一下我如果要做到一樣的效果,必須要先解析 *.torrent 檔案的結構。這不難,已經有完整的 Spec Wiki 可以看。首先要面對的是 BT 最常用到的 Bencode 編碼法 (念作 Bee encode)。
以虛擬碼來說是 ["HelloWorld", 10]
以虛擬碼來說是 {"HelloWorld": 10, "test": "true"},注意數字不能做索引鍵,必須使用字串
所以像是
{"info":
{
"1" : {"date": 20090204203645, "file": ["A", "B", "C"]},
"2" : {"date": 20090203123559, "file": ["01.jpg", "2.png", "3333.txt"]}
}
}
這種結構也能輕易的變成Bencode:
d4:infod1:1d4:datei20090204203645e4:filel1:A1:B1:Cee1:2d4:datei20090203123559e4:filel6:01.jpg5:2.png8:3333.txteeee
藉由官方的Bencode套件我們馬上就可以省去這些繁複的動作,剩下的便是看 Spec 取出適當的資訊組合之後向 Tracker 要求目前的熱烈度如何即可。
又,Tracker得知熱烈度的方法是 GET /scrape?info_hash=XXX 的方法,info_hash是啥碗糕?其實就是 Torrent 檔案內 info 項目的 Bencode 資料經過 SHA-1 後的 20 bytes 資料。這邊利用 Python 提供的 hashlib 函式庫 sha1 方法來達成,至於要抓 info 的原始 bencode 資料也不會很難,我是直接再把解析完的 info 再 bencode 一次,不過照理說直接從檔案中抓效率可能比較好。
Tracker 回傳的格式一樣是 bencode,結構簡單多了。我們需要的正是 complete, incomplete 這兩項。downloaded 是已下載完成的人次,可作為一種熱門參考,但前面兩個值對下載比較重要。
經過解析後的 torrent 檔案,我們需要 announce-list 列表中的 Tracker 作查詢,另外 info 需要被作成 SHA-1 hash 來和 Tracker 聯繫。剩下的便是一一向 Tracker "Scrape" 目前的下載情形 (/announce 改成 scrape 就可以了),將 HTTP GET 的內容給解碼後,就可以抓 'complete', 'incomplete', 'downloaded' 三個有用資料。如此向每一個 Tracker 要求之後就可以得知熱烈度,藉以決定值不值得一試。
最後感謝網際網路的便利性,讓我很快地找到需要的資料:
- Python 教學文件
中文翻譯版的教學,將我不懂的語言語法直接列出來可以看,很不錯 - BitTorrentSpecification - TheoryOrg
Torrent 檔案解析、Bencode、scrape 呼叫法跟回傳的內容都介紹的很清楚 - [bittorrent] 从http tracker 获取peers - 倚天龍記 - CSDNBlog
搜尋得來有關 info_hash 如何產生的說明及程式碼範例
---
02/05: 修正程式碼中有關 scrape 回傳的 Bencode 偵測問題,有的 Tracker 只回傳 i0e (0) 會導致原本的判斷錯誤,現改用判斷型態為 dict 才作處理。
沒有留言:
張貼留言