BT源代碼學習心得(十五):客戶端源代碼分析(下載過程中的塊選取策略)

BT源代碼學習心得(十五):客戶端源代碼分析(下載過程中的塊選取策略)

發信人: wolfenstein (NeverSayNever), 個人文集
標  題: BT源代碼學習心得(十五):客戶端源代碼分析(下載過程中的塊選取策略)
發信站: 水木社區 (Thu Aug 18 22:25:42 2005), 文集
(本文包含HTML標記,終端模式下可能無法正確瀏覽)
    上一次介紹了對等客戶之間在連接建立後的一些動作,以及BT中的阻塞控制策略。這一
次將介紹當某個連接終於暢通時,雙方的數據交互,也以此爲基礎介紹BT中另一重要的策略
控制器PiecePicker。
    Choker在選擇瞭解除一個連接的阻塞後,Upload.unchoke()將會執行,Connection對象
的send_unchoke()也在此被執行。當網絡的另一端收到這條消息後,它對應的
SingleDownload.got_unchoke()將會開始進行處理。它再檢查自己的interested狀態,如果
自己也感興趣的話,那麼就用_request_more()開始向對方請求數據了。
    _request_more()可以給一個indices作爲參數,這個參數是一個列表,意思就是說優先
下載號碼在這個列表中的塊。如果這個參數爲None,那意思就是說你自己看着辦吧,覺得下
哪塊合適就下哪塊。首先檢查自己的active_requests,就是當前連接中已經發出去的請求
,如果已經發出去的請求太多了(而還沒有數據返回),就暫時不發出新的請求了而是直接返
回。下面檢查endgame,如果已經進入這個階段則按照這個階段的方式去下載
(fix_download_endgame(),收尾階段特殊方式下載)。
    接下來就開始生成請求了,首先檢查indices,如果是None,那麼讓PiecePicker來挑一
塊,否則,逐個的檢查indices中的值,如果這個號碼的塊對方有(have[i])而自己又想要
(do_I_have_requests(i)),那麼就是它了。PiecePicker如何進行塊的選取的策略我們稍後
再分析,現在我們知道的就是它已經決定下載某一塊了。然後要檢查interested,如果有必
要,還要通知一下對方。下面一段就是不斷向StorageWrapper要網絡請求的參數,
new_request根據自己在硬盤上的某一塊的擁有情況,不斷得返回塊內相對偏移和長度。在
這裏,我們可以看出,對等客戶之間要求傳輸實際的數據的請求有三個參數,即第幾塊,塊
內偏移多少,長度多少。而這個長度是根據配置文件中的參數決定的,通常就是一個slice
,它要能一次下載完。當然,一塊的長度不一定是slice的整數倍,因此最後一個slice的長
度要短一些,不過,這些細節在StorageWrapper中已經處理好了。從StorageWrapper得到請
求後,就把它加到自己的active_requests中,然後讓自己的Connection對象去
send_request()。現在我們也應該更加清楚active_requests和inactive_requests的意義了
,即平時StorageWrapper根據實際情況,準備好inactive_requests,然後在
SingleDownload對象中請求發出時,把它們逐漸轉移到自己的active_requests中。
    在兩個while循環的下面,檢查active_requests,意思就是說如果經過以上的所有過程
,如果active_requests還是空的,那麼說明什麼呢?只能說明對方根本就沒有(或者說曾經
有,但是現在已經沒有了)自己感興趣的數據,而如果自己還是interested的話,要調用一
個send_not_interested(),意思是我不再對你感興趣了。下面檢查lost_interests中的值
,這些都是在下載過程中曾經是自己想要的,但是現在已經不想要了(主要原因是自己已經
擁有了)。接下來這個for循環的意思就是檢查所有的SingleDownload對象,告訴它們某一塊
已經有了,不用再去下了,而且有些SingleDownload要因此發出NOT_INTERESTED。最後再次
檢查是否進入endgame階段,如果是,則按照這種階段的行爲進行處理。
    現在我們就可以來研究PiecePicker這個塊選擇策略控制器的行爲了,從前面的分析我
們知道,每個PiecePicker對應一個_SingleTorrent,使用它時經歷了以下幾步:首先是初
始化,然後根據自己已經有的塊,把它告訴給PiecePicker(complete(i)),以後就不要從這
中間選了,還有就是當一個SingleDownload對象獲取對方的塊擁有狀況位圖時,也要告訴
PiecePicker(got_have(i)),意思是這一塊有人有了。最後當需要PiecePicker做出選擇時
,只要調用其next函數,它需要一個判斷函數(_want),以及一個對方是否是種子的標誌
(self.have.numfalse == 0),_want函數就是這樣的一個函數,當PiecePicker選了一塊後
,要拿給它檢查,看看這一塊是不是它確實想要的,如果不是的話,PiecePicker會重新選
擇。而_want()函數的判斷標準很簡單,那就是別人有而自己又想要的。
    PiecePicker的初始化工作主要是對自己的內部變量進行。這裏要解釋一下這些變量的
作用,這樣能夠更加方便地對後面的部分進行理解。numpieces,總的塊數。interests是按
照擁有者的數量排序的塊列表的列表,就是說,它是一個列表,列表中的第0個元素是所有
的自己感興趣而沒有人有的塊的列表,第1個元素是所有的自己感興趣而只有一個人有的塊
的列表,等。pos_in_interests,就是每一塊在interests中的對應元素所表示的列表中的
位置,如果某一塊比如說i,自己已經有了,那麼pos_in_interests[i]的值沒有意義。
numinterests的值就是某塊有多少人擁有(不包括自己),以上三個變量保持這樣的關係:如
果一塊i,自己沒有,那麼interests[numinterests[i]][pos_in_interests[i]]=i。have是
一個布爾數組,表示自己已經有那塊,在初始化完成後,它應該和StorageWrapper中的實際
情況保持一致。crosscount則是一個統計情況數組,即有多少塊沒有人擁有,有多少塊有一
個人擁有,等,自己擁有的某一塊也在這裏參加計數。numgot,已經得到的塊數。
scrambled,一個包含從0到numpieces-1的序列,但是被隨機打亂了。
    現在來看PiecePicker.complete,即自己有了某塊,首先have中的值要設置,然後從
numinterests中查到自己原來有多少人擁有,把crosscount中對應的項減一,然後把它下一
項加一,如果沒有下一項,那麼就在後面添加一項。由此我們可以看到,crosscount數組是
逐漸增大的。然後它做的事情是把interests中的對應的項刪除掉,因爲它已經不在自己感
興趣的範圍內了,其它幾行代碼是爲了保持這些變量值的一致性。然後試圖從started和
seedstarted中刪除這一塊(如果沒有這一塊也無所謂,什麼也不用做)。
   PiecePicker.got_have,處理的情況是別人有了某一塊。首先還是保持crosscount的一
致,然後處理interests列表。調用_shift_over把piece從interests列表中的一個元素轉移
到另一個元素(同時還要保持其它變量的值的意義的一致性)。_shift_over做的事情就是從
第一個列表中刪除一個元素,然後將其插入第二個元素隨機的位置,同時維護
pos_in_interests值的意義。
    PiecePicker.requested,哪一塊已經開始下載了,這個在SingleDownload中會被調用
,它只是維護兩個列表,started和seedstarted。
    PiecePicker.next,可以說是PiecePicker中提供的最重要的功能,選擇一塊進行下載
。它選擇的第一條原則是,已經開始下載的優先把它下載完(return choice(bests)及其前
面的代碼)。它檢查選擇的兩個數組,根據對方是否是種子選擇一個數組。然後在所有的這
個數組中選擇出自己想要的,檢查它們的numinterests,即擁有此塊的人數,選出擁有人數
最少的塊,放入bests中,如果有並列的,則添加到bests,因此在這裏結束後,bests中的
元素是所有正在下載的且自己想要的塊中擁有人數最少的塊的列表,那麼就從中間隨機選擇
一個返回即可。選擇的第二條原則是,當自己擁有的塊數少於一定的數量時,隨機選擇自己
想要的塊進行下載(第一階段結束後的那個if塊),因此它用到了那個scrambled列表,而當
自己所擁有的塊數超過一定的值(config['rarest_first_cutoff'])後,執行第三階段的方
案。選擇的第三條原則是,優先選擇下載擁有的人數最少的塊,我們看到,它從interests
中第1個元素開始檢查,選擇最先找到的自己想要的塊,第0個元素不用檢查,因爲沒有人擁
有的塊肯定下載不到。我們可以看出,它的選擇原理是比較簡單但是又很有效的,優先下載
擁有人數最少的塊就能夠保證所有的塊能夠在最短的時間內儘可能得讓更多的人擁有,換一
個術語說就是能儘快提高要下載的內容的副本率。
    這一次我們分析了對等客戶在下載的過程中,如何進行下載的策略控制。下一次將分析
收到對方的下載請求後的處理方式等。
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章