从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 协议 待实现
 
posted @ 2021-05-23 14:10  宁次  阅读(232)  评论(0编辑  收藏  举报