BT源代码学习心得(六):跟踪服务器(Tracker)的代码分析(初始化)
author:wolfenstein

Tracker在BT中是一个很重要的部分。这个名词我注意到以前的文章中都是直接引用,没有翻译过来,想了一下,决定把它翻译成跟踪服务器。
    在BT下载中,种子文件表明了要下载的文件的信息和对它进行检查的消息摘要码,但是每个对等客户(peer,以后我把peer全部翻译成对等客户,以区别 client)要获取其它对等客户的信息时,还是要和跟踪服务器联系的。跟踪服务器上面不保存任何和种子所代表的内容有关的文件,它只记录所有下载该种子 的机器的IP地址,端口等信息,并在客户向它请求是返回一些这样的信息列表,具体的实际内容,由对等客户之间完成交互。
    跟踪服务器的代码实现在BitTorrent/track.py中,在bttrack.py中只是很简单得一行:
    track(argv[1:])
    这样就把参数传到track.py的track函数。track函数本身也比较简单,处理参数和相关的配置文件,建立一个RawServer,然后用 create_serversocket创建服务器套接字,然后开始服务。关于在BT中使用网络服务上次已经有很详细地介绍,这里不再重复。只是针对 tracker函数的具体情况,分析一下运行到listen_forever后的情况,首先,建立了Tracker对象,打开了在某个端口 (config['port'])侦听的网络服务,这个函数的处理对象是一个HTTPHandler。所以我们要分析程序的流程只需要先分析 Tracker的初始化函数,看看它创建后都做了些什么,然后再看HTTPHandler实际分析它的网络协议。
    在Tracker对象的初始化函数中,首先还是对各种变量的初始化。然后要从一个状态文件中进行一些状态恢复,也就是恢复state变量。这个变量中的值 很重要,我们可以需要从一些地方来得知它的结构,状态文件的读取和保存出得不到它的信息,因为这两处的实现方式就是bencode和bdecode,只能 保证无论state的结构是什么都能合适得被保存和恢复,由此又看出bencode编码设计的巧妙。但是有一个函数对我们分析state的内部结构很有帮 助,那就是statefiletemplate,这个函数检查state中的值是否合法,因此我们可以从这里得到state的一些结构信息。
    首先,state必须是一个字典类型的变量。然后检查每一项的值。如果发现一项关键字是'peers',那么它的值必须也是一个字典,这个字典是一个以种 子文件的信息部分的消息摘要值为关键字的字典,由于sha摘要算法比较好得满足了摘要算法的要求,即不同的种子文件它们生成相同摘要的概率极小。而且由于 这是由种子文件的内容生成的摘要值,因此即使把种子文件改名,还是可以识别出来是哪个种子文件。因此'peers'的值可以看成是为每一个种子文件记录的 信息,那么为每个种子文件记录的是什么信息呢?这个信息又是一个字典,这次以每个对等客户的ID为关键字,每个对等客户在连接到跟踪服务器的时候都会为自 己生成一个ID,这个ID怎么生成的以后看客户端的代码可以知道,现在我们知道的是,它的长度必须为20。这个字典的值,嗯,又是个字典,不过这个字典的 意义就明显多啦,包括了IP是多少,端口是多少,还剩多少没有下载完。因此state的内容可以看成是这样的:{'peers':{},...},其中 peers的结构是这样的:{hash1:{ID1: {'ip':xxx.xxx.xxx.xxx,'port':xxxx,left:XXXX},ID2: {'ip':yyy.yyy.yyy.yyy,'port':yyyy,left:YYYY},...},hash2:{...},...}。以上是 state中'peers'这一项。'completed'这一项就相对结构简单了,它记录的是每个种子文件的下载完成情况,它的结构是个字典,以每个种 子的信息部分的消息摘要值为关键字,而对应的值就是一个整数,表示该种子文件已经有多少人完成了下载。接下来是'allowed'项,这项记录了该跟踪服 务器所关注的所有的种子的信息,仍然以信息部分的消息摘要值为关键字,内容就是该种子文件的实际信息,从后面的分析(对 BitTorrent/parsedir.py的分析)可以知道是哪些信息,另外由于之前对种子文件的内部结构我们已经比较清楚,所以也可以猜出部分。 state中还有'allowed_dir_files'项,这一项也是记录文件信息的字典,但它是以每个文件的文件名为关键字(而不是消息摘要值),每 个文件的项目是一个列表,结构如下:[(文件修改时间,文件大小),消息摘要值],就是说,这个以文件名为关键字的字典它的每一个值都是一个列表,这个列 表有两个元素,第一个元素是一个二元组,内容是文件修改时间和文件大小,第二个元素是消息摘要值。最后,我们注意到statefiletemplate在 处理'allowed'项和'allowed_dir_files'项时还有一些额外的检查代码,即所有在'allowed'项里面出现的元素,它的消息 摘要值都必须在'allowed_dir_files'项中出现,且'allowed_dir_files'中所有的项中的值的消息摘要部分必须在 'allowed'中出现,另外'allowed_dir_files'中不得出现重复的消息摘要值('allowed'项本身就以消息摘要值为关键字, 而字典的关键字已经保证不会重复)。
    因此现在我们知道了state中的注意部分的结构。下面我们注意这两句:
    self.downloads    = self.state.setdefault('peers', {})
    self.completed    = self.state.setdefault('completed', {})
    这样就把state中的'peers'和'completed'的值传到了downloads和completed中,更重要的是,以后在跟踪服务器的运 行过程中,如果'peers'和'completed'的值发生改变(那简直是一定的),state中的相应值也会发生变化,这样,保存dfile时,就 可以及时更新state的值了。以后我们分析跟踪服务器运行过程的时候少不了和它们打交道,现在我们可以先记住,downloads保存了所有的下载的客 户端的信息,completed保存所有的种子的下载完成情况的统计信息。
    下面的这个for循环根据配置文件处理NAT的问题,以及计算种子的个数。completed只是记录所有下载完成的客户的数目,而只有已经下载完成 (left=0),但是还在downloads中出现(即下载完毕但是没有关闭客户端)的客户端才算是一个种子。这里我们可以很容易得看 出,seedcount是一个以信息摘要为关键字,整型为值的统计种子数的一个字典。
    下面是一个计算的变量,times表示了每个种子(以信息摘要为关键字)中每个客户(以客户ID为关键字)的上次的有活动的时间。接下来增加了两个任务,每隔一段时间保存一下dfile,并且检查下载的客户端是否已经有很长时间没有反应的。
    接下来准备一个日志文件,并试图把标准输出重定向到这个日志文件中。
    最后要去寻找该跟踪服务器所关注的所有的种子,即parsedir,这个函数可以自己去看,相信在知道了种子文件的编码格式和前面的状态中的项的要求后, 不难分析。总得说来,这个函数做了以下事情,即寻找某个目录下所有的.torrent文件,把这些文件中的信息读取进来,并且排除错误,重复等等不合要求 的,然后进行加工,输出符合要求的结果,储存在allowed和allowed_dir_files中,进而影响state。
    现在tracker对象已经建立起来,它已经有它要进行跟踪的所有种子的信息,并且准备好了维护所有连接进来的客户的列表,因此它可以正式开始提供跟踪服务了。下一次我们就可以看看tracker动起来的效果。

BT源代码学习心得(六):跟踪服务器(Tracker)的代码分析(初始化) -- 转贴自 wolfenstein (NeverSayNever)相关推荐

  1. BT源代码学习心得(六):跟踪服务器(Tracker)的代码分析(初始化)

    BT源代码学习心得(六):跟踪服务器(Tracker)的代码分析(初始化) 发信人: wolfenstein (NeverSayNever), 个人文集 标  题: BT源代码学习心得(六):跟踪服务 ...

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

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

  3. BT源代码学习心得(八):跟踪服务器(Tracker)的代码分析(用户请求的实际处理) - 转贴自 wolfenstein (NeverSayNever)

    BT源代码学习心得(八):跟踪服务器(Tracker)的代码分析(用户请求的实际处理) author: wolfenstein 通过上一次的分析,我们已经知道了Tracker采用http协议和客户端通 ...

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

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

  5. BT源代码学习心得(四):种子文件的生成 -- 转贴自wolfenstein (NeverSayNever)

    BT源代码学习心得(四):种子文件的生成 author: wolfenstein 在知道种子文件采取的编码方式后,我们现在可以来看一个种子文件具体是如何生成的了.在BT中,生成种子文件的可执行模块是 ...

  6. BT源代码学习心得(四):种子文件的生成

    BT源代码学习心得(四):种子文件的生成 发信人: wolfenstein (NeverSayNever), 个人文集 标  题: BT源代码学习心得(四):种子文件的生成 发信站: 水木社区 (We ...

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

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

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

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

  9. BT源代码学习心得(一):总体描述

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

最新文章

  1. php里面的log是什么文件夹,用PHP生成自己的LOG文件
  2. 解决无法将类型为“System.Web.UI.WebControls.HiddenField”的对象强制转换为类型的错误...
  3. 一个释放临时表空间的实例
  4. 学习Java编程到底是为了什么,该具备什么样的能力
  5. J-LINK segger 驱动,MDK5.15版本,用于解决**JLink Warning: Mis-aligned memory write: Address: 0x20000000......
  6. Selenium WebDriver的TestNG注释完整指南
  7. php rpoplpush,Redis Rpoplpush 命令
  8. Linux中的报错命令,Linux学习教程-Linux下命令的一些异常情况
  9. 检查虚拟机是否使用virtio
  10. 底层I/O性能大PK:Python/Java被碾压,Rust有望取代C++
  11. windows xp 的开机黑屏只有光标闪动的解决方法
  12. NO.128 开发团队篇:参加项目计划会议,分解任务,领取任务,每天更新任务。...
  13. 《数学之美》—闪光的不一定是金子
  14. [Swift通天遁地]一、超级工具-(11)使用EZLoadingActivity制作Loading加载等待动画
  15. MCS:连续随机变量——Erlang分布
  16. linux/windows下代理软件对比分析
  17. 《羊了个羊》谁还在玩我笑他两年半
  18. 物品分类游戏html5,物品的用途分类教案
  19. python输入姓名输出欢迎你某某同学_Python交互环境下打印和输入函数的实例内容...
  20. 淘宝电商项目落地,从零开始搭建亿级系统架构笔记

热门文章

  1. Mysql启动时pid未更新_MySQL启动报错 无法更新PID文件
  2. 解决:The ‘Access-Control-Allow-Origin‘ header contains___Nginx跨域设置
  3. 如何把多个js函数绑定到事件上面
  4. 在vue新版脚手架中下载和使用jquery
  5. 【问题记录】更换域名的DNS时,浏览器许久不生效。
  6. 网页前端监控系统(错误日志,接口监控)的使用
  7. php中Sessionopen,php使用session提示[function.session-start]: open解决方法
  8. m基于matlab的光通信误码率仿真,分别对比了OFDM+BPSK和OFDM+4QAM的误码率和星座图
  9. 27岁从业软件测试5年的我被无情的辞退了
  10. MacM1本地navicat无法连接本地docker的mysql。