使用C++编写一个DHT爬虫,实现从DHT网络爬取BT种子

使用C++编写一个DHT爬虫,实现从DHT网络爬取BT种子

  • 1、前言
  • 2、相关术语
    • 2.1、P2P网络
    • 2.2、DHT网络
    • 2.3、Kademlia算法
    • 2.4、KRPC协议
    • 2.5、MagNet协议
  • 3、BT下载的一些概念梳理
    • 3.1、BT软件下载原理
    • 3.2、迅雷获取种子的速度为什么那么快
    • 3.3、资源时效性问题
    • 3.4、好用的BT软件
    • 3.5、有没有已经编写好的DHT爬虫
  • 4、使用C++编写DHT爬虫
    • 4.1、实现原理
    • 4.2、实现DHT协议
      • 4.2.1、创建UDP服务
      • 4.2.2、加入DHT网络
      • 4.2.3、报文解析
      • 4.2.4、对不同类型报文进行处理、回复
      • 4.2.5、隐藏自己,防止被其他节点拉进黑名单
      • 4.2.6、获取info_hash和peer
    • 4.3、实现BitTorrent协议
      • 4.3.1、HandShake(握手)
      • 4.3.2、Extend HandShake(扩展握手)
      • 4.3.3、获取metadata
      • 4.3.4、制作torrent文件
  • 4、总结

使用C++编写一个DHT爬虫,实现从DHT网络爬取BT种子

2、相关术语

2.1、P2P网络

使用C++编写一个DHT爬虫,实现从DHT网络爬取BT种子

DHT(Distributed Hash Table,分布式哈希表),DHT由节点组成,它存储peer的位置,是一种分布式存储方法。在不需要服务器的情况下,每个客户端负责一个小范围的路由,并负责存储一小部分数据,从而实现整个DHT网络的寻址和存储,其中BT客户端包含一个DHT节点,用来联系DHT中其他节点,从而得到peer的位置,进而通过下载。
简单点来说DHT就是负责管理提供信息和服务节点的管理与路由功能,这里有两个需要区分的概念:

  • peer:是在一个 TCP 端口上监听的客户端/服务器,它实现了BitTorrent协议
  • 节点:是在一个 UDP 端口上监听的客户端/服务器,它实现了DHT(分布式哈希表) 协议

2.3、Kademlia算法

Kademlia是DHT网络的一种实现。在Kademlia网络中,距离是通过异或(XOR)计算的,结果为无符号整数。distance(A, B) = |A xor B|,数值越小表示越近两个节点越接近,详细说明可以自行百度查阅。

2.4、KRPC协议

KRPC是节点之间的交互协议,是由B编码组成的一个简单的RPC结构,它使用UDP报文发送,一个独立的请求包发出去,然后由另一个独立的包来回复(这也是UDP无连接特性所决定的,所以协议中肯定也会有让我们区分报文包的方法),要注意的是这个协议没有重发机制。

2.5、MagNet协议

MagNet协议,也就是磁力链接。是一个通过sha1算法生成一个20字节长的字符串,P2P客户端使用磁力链接,下载资源的种子文件,然后根据种子文件下载资源。

3、BT下载的一些概念梳理

3.1、BT软件下载原理

BT软件使用,通过击鼓传花的方式,在DHT网络上搜寻磁力链接对应的资源,当找到拥有此资源的peer之后,使用先将种子下载下来,然后根据种子文件内容下载对应的资源。

3.2、迅雷获取种子的速度为什么那么快

从理论上来讲,由于BT软件要先去DHT网络搜寻种子,这个过程时需要耗费一定时间的,所以要做到大部分资源都迅速响应是不可能的,迅雷那么快的原因只有一个,就是迅雷自己有种子库,里面缓存了其他用户下载过的种子或者迅雷自己平时在DHT上面爬取的种子。

3.3、资源时效性问题

当DHT网络上持有某一资源的peer全部停止工作后,资源自然也就下不了了,迅雷由于自己有服务器缓存了以往一些热门的资源,所以往往会给人造成资源还在的假象,其实此时是迅雷自己充当服务器给你下发资源而已(这也就是为什么有些资源充了VIP才能下的原因了,毕竟服务器不能让你白用)。

3.4、好用的BT软件

既然BT的原理都是加上,所以不同软件下载速度啥的应该差别不大(有服务器缓存支撑的软件除外),比较出名的BT软件有迅雷、uTorrent、qBittorrent、比特彗星、Transmission、aria2等等,大家可以自行去百度去搜索。

3.5、有没有已经编写好的DHT爬虫

答案当然是有的啦,所有BT软件肯定都实现了和,可以看一些开源的BT软件里面的实现方法,有个叫做的库非常著名,很多BT软件都是将其套个壳做出来的,只不过代码写的比较复杂,看起来有点难受。于是乎就想看看有没有人已经用比较简单的方式实现了DHT爬虫,而通过查阅了很多文章,发现有些人是只实现了DHT协议,然后拿那些通过DHT网络爬取到的hash去开源种子库获取种子,有些就是没有把BitTorrent协议的实现方法开源出来,所以萌生了自己做一个完整的DHT爬虫的想法(开源库无法获取到最新的资源,而且速度肯定是不如直接在DHT网络爬取的)。

4、使用C++编写DHT爬虫

4.1、实现原理

伪装成DHT节点加入DHT网络中收集信息,爬虫主要收集get_peer、announce_peer这两个请求的信息。当收到get_peer或者announce_peer的请求时,直接使用从请求发起者下载对应的种子信息(获取不到种子的概率会比较大,原因大家自行完整看一下DHT协议就明白了)
这里有一个疑问,要如何加入DHT网络,通过查看其他大神们的开源代码,我发现基本都是ping下面三个节点来加入DHT网络的

域名 端口
router.utorrent.com 6881
router.bittorrent.com 6881
dht.transmissionbt.com 6881

4.2、实现DHT协议

4.2.1、创建UDP服务

创建一个UDP服务,监听6881端口(DHT默认端口,可以自行修改,理论上啥端口都可以)

4.2.2、加入DHT网络

通过ping上面那几个节点来将自己加入到DHT网络中,这样才能获取到节点的消息,实现如下:

4.2.3、报文解析

收到其他节点发过来的报文之后,进行报文解析,DHT网络中互相之间通信的格式是B编码,不了解B编码的可以去看这篇文章《B编码与BT种子文件分析,以及模仿json-cpp写一个B编码解析器》,解析报文的代码如下:

来源:彼 方

声明:本站部分文章及图片转载于互联网,内容版权归原作者所有,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2021年5月12日
下一篇 2021年5月12日

相关推荐