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个元素不用检查,因为没有人拥
有的块肯定下载不到。我们可以看出,它的选择原理是比较简单但是又很有效的,优先下载
拥有人数最少的块就能够保证所有的块能够在最短的时间内尽可能得让更多的人拥有,换一
个术语说就是能尽快提高要下载的内容的副本率。
    这一次我们分析了对等客户在下载的过程中,如何进行下载的策略控制。下一次将分析
收到对方的下载请求后的处理方式等。

BT源代码学习心得(十五):客户端源代码分析(下载过程中的块选取策略)相关推荐

  1. BT源代码学习心得(十):客户端源代码分析(相关对象一览) -- 转贴自 wolfenstein (NeverSayNever)

    BT源代码学习心得(十):客户端源代码分析(相关对象一览) Author:wolfenstein(NeverSayNever), BitTorrent/download.py中的Multitorren ...

  2. BT源代码学习心得(九):客户端源代码分析(图形界面浅析) -- 转贴自 wolfenstein (NeverSayNever)

    BT源代码学习心得(九):客户端源代码分析(图形界面浅析)  author:wolfenstein 客户端将从btdownloadgui.py开始进行分析,这样可以顺便把Python中的GUI编程也看 ...

  3. BT源代码学习心得(十三):客户端源代码分析(对等客户的连接建立及其握手协议)

    BT源代码学习心得(十三):客户端源代码分析(对等客户的连接建立及其握手协议) 发信人: wolfenstein (NeverSayNever), 个人文集 标  题: BT源代码学习心得(十三):客 ...

  4. 转贴: wolfenstein工作室-eMule源代码学习心得

    1, eMule源代码学习心得(1):eMule代码的总体风格和其它相关工程 eMule的官方首页上写着:2002年05月13日 一个叫做 Merkur 的人,他不满意原始eDonkey2000客户端 ...

  5. STM32学习心得十九:电容触摸按键实验及相关代码解读

    记录一下,方便以后翻阅~ 主要内容 1) 电容触摸按键原理: 2)部分实验代码解读. 实验内容 手触摸按键后,LED1灯翻转. 硬件原理图 上图,TPAD与STM_ADC用跳线帽相连,即TPAD与PA ...

  6. STM32学习心得十八:通用定时器基本原理及相关实验代码解读

    记录一下,方便以后翻阅~ 主要内容: 1) 三种定时器分类及区别: 2) 通用定时器特点: 3) 通用定时器工作过程: 4) 实验一:定时器中断实验补充知识及部代码解读: 6) 实验二:定时器PWM输 ...

  7. BT源代码学习心得(五):统一网络服务接口--RawServer -- 转贴自 wolfenstein (NeverSayNever)

    BT源代码学习心得(五):统一网络服务接口--RawServer author:wolfenstein 以后的部分都需要网络服务(种子文件的生成在本地就可以完成,但是通过这些种子文件下载实际的内容和提 ...

  8. BT源代码学习心得(一):总体描述 -- 转贴自wolfenstein (NeverSayNever)

    BT源代码学习心得(一):总体描述 发信人: wolfenstein (NeverSayNever), 个人文集 标  题: BT源代码学习心得(一):总体描述 发信站: 水木社区 (Fri Jul ...

  9. BT源代码学习心得(七):跟踪服务器(Tracker)的代码分析(HTTP协议处理对象) -- 转贴自 wolfenstein (NeverSayNever)

    BT源代码学习心得(七):跟踪服务器(Tracker)的代码分析(HTTP协议处理对象) author: wolfenstein (NeverSayNever) 上次我们分析了Tracker类初始化的 ...

最新文章

  1. sqlserver查找存储过程关键字方法之三
  2. 今日arXiv精选 | 18篇近期值得关注的Transformer工作
  3. mysql触发器学习的一个小错误
  4. 吐槽net下没有靠谱的FastDFS的sdk之使用thrift实现JAVA和C#互通
  5. 一分钟了解:zigbee的三种关键角色(视频讲解)
  6. java好学吗谁学过说话,最全Java知识总结
  7. 1、视觉slam简介
  8. OPPO 实时数仓揭秘:从顶层设计实现离线与实时的平滑迁移
  9. PS 如何去掉图片中的水印
  10. 新趋势下的云计算安全行业前沿认证 | CCSK
  11. robo3t怎么插入数据_使用Robo 3T操作MongoDB数据库
  12. 内网穿透和路由器端口映射什么区别?
  13. 工作薄与工作表的区别:
  14. 计算机领域国际期刊,科学网—计算机国际期刊zz - 黄红星的博文
  15. matlab图形黎曼几何,黎曼几何是篡改数学概念的几何
  16. 51单片机LED灯闪烁
  17. 什么是单工,半双工,全双工
  18. 程序员常用工具网站汇总(一)
  19. 史诗级聊天AI ChatGPT来啦!
  20. 生信分析之R语言常用R包一步下载

热门文章

  1. 常量指针(Pointer to const)与指针常量(Const pointer)
  2. html段前段间距设置,Word里标题段前距设置不管用,段后管用
  3. STL 源码分析: RB_tree 红黑树(三) 插入和查找
  4. Hadoop中怎么解决Starting secondary namenodes [0.0.0.0]
  5. HEVC 高级运动向量预测技术(AMVP)
  6. windows下hadoop安装时出现error Couldn‘t find a package.json file in “D:\\hadoop\hadoop-2.7.7\\sbin“问题
  7. 谷歌研究——四足机器人模仿动物动作
  8. 【面朝大厂】面试官:你对MySQL中的索引了解多少?
  9. xls和xlsx的区别
  10. 如何实现按键的短按、长按检测?