• 从0实现 BT 下载 :2 Tracker 服务交互


    在上一篇 1种子的解析 介绍了种子的解析,已经可以解析出来关键的信息了:

    announce list: Tracker 服务器列表

    info_hash:文件 SHA1 20Byte 经过 URL 编码

    peer_id:客户标识

    先看一个真实请求样例:

    * example
    curl -v "http://share.camoe.cn:8080/announce?info_hash=%87%2F%DF%A8K%97%B5%EC%7B%A6h%CA%B5%FF%28%40%FEK%22%0F&peer_id=%2DSD0100%2D%7Ef%5C%C5%1D%0E%A0%FEj%C3%C6%E5&ip=172.16.18.152&port=8797&uploaded=31354&downloaded=0&left=378440308&numwant=200&key=202&compact=1&event=started"

    协议分为3种:udp http https ,udp 先不考虑实现,http https 2个都要实现的话,用 libcurl 是最为简单的,如果仅实现 http 使用纯 socket 也可以,https 如果不使用 libcurl 就必然用到 ssl 库。所以综合考虑还是先使用 libcurl 实现,当然后期想移除也可以。

    思路是这样的:

    解析完种子以后,循环每个 Tracker 分别调用 http 请求方法,多线程并发调用 ,有响应的 Tracker 服务器,将结果 回调通知出来,在统一做解析处理。

    运行后结果如下:

    已经可以得到 响应了,接下来就是解析处理

    winhex 打开 不能在用 notepad++ 了容易产生误判

    关键字段:

    #pragma pack(push)
    #pragma pack(1)
    typedef struct peer_t
    {
    	unsigned char ip[4];
    	unsigned char port[2];
    } peer_t;
    #pragma pack(pop)
    
    int complete; //下载完成的
    int incomplete; //正在下载的
    int downloaded; //下载完成的
    int interval; //下次请求时间
    int min_interval; //最小请求时间限制
    int peers; //客户端ip port 列表 用上面的 结构体解析 注意字节对齐
    

      

     

    解析出来 结果

    void Tracker::peersDecode(const char *buff, int len)
    {
        int i = 0;
        std::string ip = "";
        int port = 0;
        peer_t *peer = (peer_t *)buff;
    
        LOG_DEBUG("buff:%s len:%d", buff, len);
    
        i = len / sizeof(*peer);
    
        while ( i-- )
        {
            if ( peer && peer->ip && peer->port )
            {
                ip = inetNtoaString(peer->ip);
                memcpy(&port, peer->port, sizeof(peer->port));
    
                LOG_DEBUG("peers ip:%s port:%d", ip.c_str(), ntohs(port));
            }
    
            peer++;
        }
    }
    std::string inetNtoaString(const unsigned char *buff)
    {
    	struct in_addr addr = { 0 };
    
    	if ( ! buff )
    	{
    		return "";
    	}
    
    	memcpy(&addr, buff, sizeof(addr));
    	return inet_ntoa(addr);
    }  
     
    其它网络模形:
     
    UDP 协议 Tracker 服务器 待实现
     
    DHT 协议 待实现
     
  • 相关阅读:
    C++中的空类,编译器默认可以产生哪些成员函数
    野指针(Wild pointer)和悬垂指针(dangling pointer)
    WHY C++ ?(by Herb Sutter) & C++17 standard
    mapreduce 多路输出
    stdout 编码 vim 删除左边,右边
    积累碎片shell
    python logging模块
    shell 流程控制
    shell 变量
    时间管理法则
  • 原文地址:https://www.cnblogs.com/ningci/p/14801082.html
Copyright © 2020-2023  润新知