zoukankan      html  css  js  c++  java
  • BT源代码学习心得(四):种子文件的生成 转自CSDN:gushenghua的专栏

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

    发信人: wolfenstein (NeverSayNever), 个人文集
    标  题: BT源代码学习心得(四):种子文件的生成
    发信站: 水木社区 (Wed Aug  3 22:22:09 2005), 文集
    (本文包含HTML标记,终端模式下可能无法正确浏览)
        在知道种子文件采取的编码方式后,我们现在可以来看一个种子文件具体是如何生成的
    了。在BT中,生成种子文件的可执行模块是btmaketorrent.py(命令行模式)或者
    btmaketorrentgui.py(图形界面模式),通过分析,可以知道它们最终都将调用函数
    make_meta_files进行种子文件的生成,区别仅仅在于提供给这个函数的参数从何而来。命
    令行模式下的程序很简单,即直接从命令行下获取参数,GUI部分的程序以后再和下载客户
    端的图形界面程序一起分析,现在我们先直接切入正题。
        BitTorrent/makemetafile.py模块中提供函数make_meta_files。它的参数意义如下:
        URL:Tracker的URL地址,在BT的协议设计中,还是需要有个服务器作为tracker来协调
    各个客户端的下载的,tracker部分的程序以后会介绍,现在只需要知道这个URL将要作为一
    条信息写入到种子文件中即可。
        file:种子文件的来源文件或目录列表(即准备要在BT上共享的资源),注意,这里的列
    表意思是该列表中的每一项都为其生成一个种子文件,而此列表中的每一项可以是一个文件
    或者是一个目录。
        flag:一个Event对象,可以用来检查是否用户要求中止程序。程序设计得比较合理,
    可以在很细的粒度下检查这个Event是否被触发,如果是则中止执行。
        progressfunc:一个回调函数,程序会在恰当的地方调用它,以表示现在的工作进度,
    在命令行模式下,这个回调函数被指向在控制台上显示进度信息的函数,在GUI模式下,这
    个回调函数则会影响一个图形界面的进度条。
       filefunc:也是一个回调函数,程序会在恰当的地方调用它,以表示现在在处理哪个文
    件。
        piece_len_pow2:分块的大小,BT中把要共享的资源分成固定大小的块,以便处理。这
    个参数就是用2的指数表示的块的大小,例如当该参数为19的情况下,则表示共享的资源将
    被分成512k大小的块为单位进行处理。
        target:目标文件地址,即种子文件的地址。这个参数可以不指定(None),则种子文件
    将与公享资源处于同一目录。
        comment:说明。一段可以附加在种子文件内的信息。
        filesystem_encoding:文件系统编码信息。
        make_meta_files的主要工作是进行一系列的检查。例如在开始的时候就检查files的长
    度(元素的个数)和target,当files的长度大于1且target不是None的时候就会报错,因为如
    果要生成多个种子文件的话,是不能指定target的(这样target只确定了一个种子文件的保
    存位置)。接下来检查文件系统的编码问题。然后把files中所有以.torrent结尾的项目全部
    刨掉,剩下的作为参数传递给make_meta_file进行处理,注意,这个函数一次生成一个种子
    文件。
        下面来看make_meta_file,它一开始计算出块的大小,以2的指数为基础。接下来找到
    种子文件的保存地址,如果有target,以target为准,否则如果要对一个目录生成种子文件
    ,则生成以那个目录名为名称,后缀".torrent"的文件。否则生成以源文件为名称,后缀
    ".torrent"的文件。
        下面调用函数makeinfo来生成一个"info"。这个info是什么东西呢?继续看。
    makeinfo首先检查传给它的path,看看是单个文件还是一个目录。如果是一个目录的话,则
    调用subfiles把这个目录下的所有文件全部列出来,这个subfiles设计得比较巧妙,使用堆
    栈的方法避免了递归调用。从subfiles得到结果后,首先对它们进行排序。然后使用变量
    fs保存这些文件的列表信息,fs是一个list结构,每个元素包含了文件名称和它的大小组成
    的二元组。接下来就是记录文件的内容了,下面的这个算法看上去有点晕,其实它的意义是
    很明确的,每次从要共享的资源里读取长度为piece_length(就是前面那个以2的指数为基础
    计算出来的块的大小)的数据,然后计算它的sha消息摘要值。如何做到这一点呢?就是根据
    那个排好序的文件列表,读出piece_length的长度的内容,如果这个文件长度不够,则再读
    下一个文件,知道长度够了或者读完所有文件为止。生成一个消息摘要后把它加入到
    pieces数组中,再读下一块,直到全部处理完。为一个文件生成info的方法类似,只是更简
    单,直接从这个文件中一块一块得处理即可。最后这个makeinfo返回的info是一个字典,它
    的数据如下:
        pieces:每一块的消息摘要值的连接。
        piece length:每一块的长度。
        files:文件的列表信息,这里由于文件顺序和生成消息摘要的顺序是相同的,以后BT
    的客户端根据种子文件的描述,就可以很清晰得确定原始的文件名和它们的大小,再配以消
    息摘要值,就可以检查下载内容是否正确了。
        name:种子文件的内部名称,种子文件可以被随便改名,但是为了识别它方便,内部还
    是起了这么一个名称的,通常用要共享的资源来命名它。
        我们注意到flag.isSet多处被检查,其中粒度最小的地方是在读取了一块之后。它返回
    后将一路返回到make_meta_files结束,这样用户随时可以中断程序的执行。
        在makeinfo返回info这个字典类型的数据后,再调用check_info这个函数对其内容进行
    检查,这个函数定义在BitTorrent/btformats.py模块中,后面在客户端进行下载的时候还
    需要检查它。
       最后我们看到的是一个类型为字典的data,其中的元素包含了announce,一个字符串,
    creation date,一个整型数据,info,又是一个字典,如果有comment的话,那么还包含了
    字符串类型的comment。
        最后把这个类型为字典的data保存到磁盘上,工作就算完成了。怎么对这种比较复杂的
    数据类型进行编码以方便保存呢?就是上次提到的bencode。
        所以我们可以看到,一个种子文件就是一个类型为字典的data编码后的情形。
  • 相关阅读:
    查看dll定义的宏
    循环调用dll库的界面时,首次正常,再次无响应
    strftime使用%F格式化日期失败
    自己程序生成的二维码部分手机无法识别
    Drools规则
    idea快捷键
    风控文档笔记
    工作笔记
    工具方法
    BIO,NIO,AIO
  • 原文地址:https://www.cnblogs.com/kokoliu/p/616909.html
Copyright © 2011-2022 走看看