posts - 56,  comments - 12,  trackbacks - 0
tracker 服务器是 BT 下载中必须的角色。一个 BT client 在下载开始以及下载进行的过程中,要不停的与 tracker 服务器进行通信,以报告自己的信息,并获取其它下载 client 的信息。这种通信是通过 HTTP 协议进行的,又被称为 tracker  HTTP 协议,它的过程是这样的:

       client tracker 发一个 HTTP GET 请求,并把它自己的信息放在 GET 的参数中;这个请求的大致意思是:我是 xxx (一个唯一的 id ),我想下载 yyy 文件,我的 ip aaa ,我用的端口是 bbb 。。。

       tracker 对所有下载者的信息进行维护,当它收到一个请求后,首先把对方的信息记录下来(如果已经记录在案,那么就检查是否需要更新),然后将一部分(并非全部,根据设置的参数已经下载者的请求)参与下载同一个文件(一个 tracker 服务器可能同时维护多个文件的下载)的下载者的信息返回给对方。

       Client 在收到 tracker 的响应后,就能获取其它下载者的信息,那么它就可以根据这些信息,与其它下载者建立连接,从它们那里下载文件片断。

 

关于 client tracker 之间通信协议的细节,在“ BT 协议规范”中已经给出,这里不再重复。下面我们具体分析 tracker 服务器的实现细节。

 

从哪里开始?

       要建立一个 tracker 服务器,只要运行 bttrack.py 程序就行了,它最少需要一个参数,就是 –dfile ,这个参数指定了保存下载信息的文件。 Bttrack.py 调用 track.py 中的 track() 函数。因此,我们跟踪到 track.py 中去看 track() 函数。

 

Track.py track()

       这个函数首先对命令行的参数进行检查;然后将这些参数保存到 config 字典中。在 BT 中所有的工具程序,都有类似的处理方式。

 

接下来的代码:

       r = RawServer(Event(), config['timeout_check_interval'], config['socket_timeout'])

    t = Tracker(config, r)

    r.bind(config['port'], config['bind'], True)

    r.listen_forever(HTTPHandler(t.get, config['min_time_between_log_flushes']))

    t.save_dfile()

 

首先是创建一个 RawServer 对象,这是一个服务器对象,它将实现一个网络服务器的一些细节封装起来。不仅 tracker 服务器用到了 RawServer ,我们以后还可以看到,由于每个 client 端也需要给其它 client 提供下载服务,因此也同时是一个服务器, client 的实现中,也用到了 RawServer ,这样, RawServer 的代码得到了重用。关于 RawServer 的详细实现,在后面的小节中进行分析。

接着是创建一个 Tracker 对象。

然后让 RawServer 绑定在指定的端口上(通过命令行传递进来)。

最后,调用 RawServer::listen_forever() 函数,使得服务器投入运行。

最后,在服务器因某些原因结束运行以后,调用 Tracker::save_dfile() 保存下载信息。这样,一旦服务器再次投入运行,可以恢复当前的状态。

 

 

其它信息:

1、  BT 源码的分布:

BT 的源码展开之后,可以看到有一些 python 程序,还有一些说明文件等等,此外还有一个 BitTorrent 目录。这些 python 程序,实际是一些小工具,比如制作 file btmakefile.py 、运行 tracker 服务器的 bttrack.py 、运行 BT client 端的 btdownloadheadless.py 等等。而这些程序中,用到的一些 python 类的实现,都放在子目录 BitTorrent 下面。我们的分析工作,通常是从工具程序入手,比如 bttrack.py ,而随着分析的展开,则重点是看 BitTorrenet 子目录下的代码。

BT 作者 Bram Cohen 在谈到如何开发可维护的代码的一篇文章中( http://www.advogato.org/article/258.html ),其中提到的一条就是开发一些小工具以简化工作,我想 BT 的这种源码结构,也正是作者思想的一种体现吧。

 

2、  我们看到, python 和我们以前接触的 c/c++ 不一样的第一个地方就是它的函数在定义的时候,不用指定参数类型。既然这样,那么,在调用函数的时候,你可以传递任意类型的参数进来。例如这样的函数:

def foo(arg):

        print type(arg)

      

       你可以这样来调用:

       a = 100

       b = “hello world”

       foo(a)

       foo(b)

 

       输出结果是:

       <type ‘int’>

       <type ‘str’>

 

       这是因为,第一次调用 foo() 的时候,传递的是一个整数类型,而第二次调用的时候,传递的是一个字符串类型。

 

这种参数具有动态类型的特性,是 c/c++ 等传统的语言是所不具备的。这也是 python 被称为动态语言的一个原因吧。 C++ 的高级特性模板,虽然也使得参数类型可以动态化,但使用起来,远没有 python 这么简单方便。

posted on 2007-01-19 00:17 苦笑枯 阅读(351) 评论(0)  编辑  收藏 所属分类: P2P

只有注册用户登录后才能发表评论。


网站导航:
 
收藏来自互联网,仅供学习。若有侵权,请与我联系!

<2007年1月>
31123456
78910111213
14151617181920
21222324252627
28293031123
45678910

常用链接

留言簿(2)

随笔分类(56)

随笔档案(56)

搜索

  •  

最新评论

阅读排行榜

评论排行榜