Chinaunix首页 | 论坛 | 博客
  • 博客访问: 167806
  • 博文数量: 36
  • 博客积分: 1466
  • 博客等级: 上尉
  • 技术积分: 380
  • 用 户 组: 普通用户
  • 注册时间: 2007-04-17 17:43
文章分类

全部博文(36)

分类: 系统运维

2007-07-05 14:48:09

BTlibtorrent/torrent_info接口笔记
作者:wrtier15   writer15(a_t)163.com
 
研究了一段时间的libtorrent,苦于对boost和asio的了解很有限,一直都没研究它的核发心部分……
为了增加士气,只好从外围好懂一点的模块着手研究……
torrent_info模块我觉得libtorrent做得很好。因为它可以方便地生成或者读取一个.torrent的信息,而不像bittorrent源码那些,读取.torrent是靠bencode/bdecode,生成.torrent却靠另外一个模块。在python读取bencode结构很方便,在C++中读取却很繁琐。torrent_info可以使libtorrent库用户无需了解太多相关的知识而可以实现BT协议,不知不说它真的做得比较好。还有将它们合并在一起,增加了模块的内聚性。另外它还提供了piece和文件位置的映射功能。
torrent_ifno接借了如下接口
要说明一下的是entry,一个entry代表的是一个bencode的一个结点。

 


class torrent_info
{
public:

        torrent_info();
        torrent_info(sha1_hash const& info_hash);
        torrent_info(entry const& torrent_file);
//从一个文件取读数据后,经过bdecode函数转换成entry,之再转输入到这里


        entry create_torrent() const;
//根据本对象现存的信息,每成一个entry对象

        void set_comment(char const* str);
//设置注释

        void set_piece_size(int size);
//设置piece大小

        void set_creator(char const* str);
//设置创建程序名称

        void set_hash(int index, sha1_hash const& h);
//设置某一piece的SHA-1 digest

        void add_tracker(std::string const& url, int tier = 0);
//添加tracker服务器,tier代表优先级,0最高

        void add_file(boost::filesystem::path file, size_type size);
//添加一个文件信息

        void add_url_seed(std::string const& url);
//添加一个url seed地址


        typedef std::vector<file_entry>::const_iterator file_iterator;
        typedef std::vector<file_entry>::const_reverse_iterator
                reverse_file_iterator;

        file_iterator begin_files() const;
//返回文件信息的迭代器

        file_iterator end_files() const;
        reverse_file_iterator rbegin_files() const;
//返回文件信息的逆向迭代器

        reverse_file_iterator rend_files() const;

        int num_files() const;
//返回文件数量

        file_entry const& file_at(int index) const;
//根据文件信息录入的序号返回文件信息


        std::vector<file_slice> map_block(int piece, size_type offset
                , int size) const;
//??

        peer_request map_file(int file_index, size_type file_offset
                , int size) const;
//??


        std::vector<announce_entry> const& trackers() const;
//返回tracker列表


        std::vector<std::string> const& url_seeds() const;
//返回url seed 列表


        size_type total_size() const;
//返回所有文件大小的总和

        size_type piece_length() const;
//返回piece长度

        int num_pieces() const;
//返回piece数量

        sha1_hash const& info_hash() const;
//返回.torrent的info_hash

        std::string const& name() const;
//返回.torrent的name

        std::string const& comment() const;
//返回注释

        std::string const& creator() const;
//返回创建程序名称


        boost::optional<boost::posix_time::ptime>
        creation_date() const;
//返回创建时间


        void print(std::ostream& os) const;
//输出所有信息到标准输出流


        size_type piece_size(unsigned int index) const;
//返回指定piece的大小,只有最后一个piece的大小不同于其它piece

        sha1_hash const& hash_for_piece(unsigned int index) const;
//返回指定piece的SHA-1 hash

};


要用代码说明torrent_info如何使用,最好的代码莫过于libtorrent的例子make_torrent.cpp

#include <iostream>
#include <fstream>
#include <iterator>
#include <iomanip>

#include "libtorrent/entry.hpp"
#include "libtorrent/bencode.hpp"
#include "libtorrent/torrent_info.hpp"
#include "libtorrent/file.hpp"
#include "libtorrent/storage.hpp"
#include "libtorrent/hasher.hpp"
#include "libtorrent/file_pool.hpp"

#include <boost/filesystem/operations.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/filesystem/fstream.hpp>

using namespace boost::filesystem;
using namespace libtorrent;

void add_files(
    torrent_info& t
    , path const& p
    , path const& l)
{
    if (l.leaf()[0] == '.') return;
    path f(p / l);
    if (is_directory(f))
    {
        for (directory_iterator i(f), end; i != end; ++i)
            add_files(t, p, l / i->leaf());
    }
    else
    {
        std::cerr << "adding \"" << l.string() << "\"\n";
        t.add_file(l, file_size(f));
    }
}


int main(int argc, char* argv[])
{
    using namespace libtorrent;
    using namespace boost::filesystem;

    path::default_name_check(no_check);

    if (argc != 4 && argc != 5)
    {

        return 1;
    }

    try
    {
        torrent_info t;
        path full_path = complete(path(argv[3]));
        ofstream out(complete(path(argv[1])), std::ios_base::binary);

        int piece_size = 256 * 1024;
        char const* creator_str = "libtorrent";

        add_files(t, full_path.branch_path(), full_path.leaf());
        t.set_piece_size(piece_size);

        file_pool fp;
        storage st(t, full_path.branch_path(), fp);
        t.add_tracker(argv[2]);

        
// calculate the hash for all pieces

        int num = t.num_pieces();
        std::vector<char> buf(piece_size);
        for (int i = 0; i < num; ++i)
        {
            st.read(&buf[0], i, 0, t.piece_size(i));
            hasher h(&buf[0], t.piece_size(i));
            t.set_hash(i, h.final());
            std::cerr << (i+1) << "/" << num << "\r";
        }

        t.set_creator(creator_str);

        if (argc == 5)
            t.add_url_seed(argv[4]);

        
// create the torrent and print it to out

        entry e = t.create_torrent();
        libtorrent::bencode(std::ostream_iterator<char>(out), e);
    }
    catch (std::exception& e)
    {
        std::cerr << e.what() << "\n";
    }

    return 0;
}



后记
开始写完前面的文档的时候傻乎乎的自己写例子,结果写了半天的代码才突然想起libtorrent/example就有个make_torren.cpp。
之后打开来看看,和自己的代码对比下,结果就不说了……

 
阅读(4411) | 评论(2) | 转发(0) |
给主人留下些什么吧!~~