BT开源项目Snark源码分析

Snark是国外一个开源Java的项目,实现了BitTorrent协议,通过分析此项目的源程序,可以更利于我们更加深入的了解当前流行的BT软件的原理,进而可以指导我们的p2p软件方面的开发。

一、在分析Snark之前,我们先简单了解BT协议, 如果想了解更多请到 http://www.bitconjurer.org。

这个协议本身可以分为以下几个部分:

1.数据编码,BT采用bencoded编码,我们可以不用细究这种编码的具体细节,我想编码目的无非是方便数据传输及解析,感觉有点类似于Java中序列化,就是一个打包和解包的过程。

2.元文件,就是我们通过所说的种子文件,通常以.torrent后缀结尾,这个文件就是描述Tracker的url,资源文件的长度、sha摘要值、文件长度、分块大小、块数等。

3.Tracker,tracker通俗的讲起一个资源定位作用,就是让客户端彼此能够发现,Tracker本身其实就是简单的HTTP服务器,它和客户端交互也是以这种协议。

4. 客户端(以下我们简称Peer)之间的互连,包括Peer之间的握手、阻塞,产生兴趣,请求及传送文件块。

5. Peer之间的选择算法,包括下载策略、结束策略、阻塞优化、反冷落策略等。

分析前先让我们简单的了解一下BT原理:

<图 一>

说明:上图描述了一个简单的文件分发过程,首先Seeder具有全部文件块1,2,3,4,5,Seeder将1,2发给A,将3,4,5发给B,然后A,B交换已方没有的块,最后A,B都有了全部的文件块,其实BT的基本思想就是这样的。

二、Snark分析

<图二>

Snark整体架构还是蛮清晰的,主要的类及相互关系如上图Peer代表与自身连接的所有其它对等协助者,Peer是通过TrackerClient类从Tracker上请求过来的。

与Peer相关的类和对象有PeerConnectionIn in,PeerConnectionOut out,PeerState,PeerState包含PeerConnectionIn和PeerConnectionOut,Peer包含PeerState,PeerConnectionIn的run当中封装了网络协议包的读入和解析,使用线程不断读取对方的网络输入,PeerConnectionOut的当中封装了一个队列sendQueue,以及网络协议的写出方法sendXXX,使用线程run方法不断向外写协议包.

Peer的管理是通过两个类来完成的,一个类是PeerCheckerTask定时完成对Peer的检查,更新Peer自身的信息,基主要功能是通过各种条件判断来改变对连接的Peer的状态(阻塞还是非阻塞),我想阻塞、非阻塞的意义在于控制带宽及优化Peer间的数据传输,Snark这块的实现不难明白,主要看上传数是否超过最大限制,如果超过需要一个个检查Peer信息,如果对方无意从本方获取数据加以阻塞,如果对方阻塞自己也加以阻塞,如果从对方下载不到数据加以阻塞,如果双方都没有阻塞找一个下载量最小的加以阻塞,另一个方面就是当上传数小于最大限制数时需要解除对一部分Peer的阻塞,如果对方有需要从本方获取数据块就解除阻塞;另外一个类是PeerCoordinator,配合PeerMonitorTask定时对所有的Peer进行检查,完成网络的自组织和传输的优化,其中PeerCoordinator中unchokePeer方法是关键方法。

在块的选择请求方面,Snark并没有按照最少优先原则选择下载块,按顺序找一个想要的块,开一个块大小(一般256K,最后一块可能略小)的缓冲,每次请求16k,当这个缓冲填满时则写到硬盘上。

数据的存储是通过Storage类完成的,存储这块并不复杂,需要通过sha摘要值判断下载的数据块是否正确,Storage创建时如果是第一次下载就会为每个文件分配一个同样大小空的硬盘空间,方便后面读写,如果断点续传,程序会计算每块的sha值和正确的相比较,如果相等就会设置该块已下载的标志,不用再请求别的Peer。

整个程序的起始于Snark类的main方法, 它通过相应种子文件的Http url发起请求,获取数据解析成MetaInfo对象方便使用,通过MetaInfo对象创建Storage对象,用于本地文件读写,创建PeerCoordinator对象,为今后所有Peer的管理类,最后创建TrackerClient(实际为一线程) 并启动,TrackerClient的作用很简单,隔一段时间(这里是一分钟)向Tracker发一次请求,获取在线的其它Peer的信息,通过PeerCoordinator的addPeer方法连接上其它的Peer,Snark选择Peer时做得很简单,没有进行各方面的参数匹配,只是机械的连接而已。

一个客户端(也是一个Peer)连接另一个Peer时,首先互发握手信息,这里Peer类中有一个handshake方法起此作用,只要协议串及Peer ID匹配,这两个Peer就正式建立连接了,建立连接后Snark会为一个Peer分配两个线程, PeerConnectionIn负责读数据解析协议,PeerConnectionOut负责写数据,然后Peer之间马上互发一个位域(一组标志本方所拥有文件的二进制数组),Peer收到对方位域后就确定对对方的态度,BT称为interested or not interested,有兴趣还是没兴趣,这一点Snark中算法比较简单,只是判断本方没有的块中只要对方有一块,就会对对方感兴趣,然后本方就会向对方发送块piece请求,Peer收到块请求后,如果处于choking(阻塞)对方状态,就不予处理,如果没有就发送请块给对方,对方收到块后,只需要交给Storage写到硬盘。

三、Snark存在的不足

1.开启线程过多,当连接数增大,会占用大量系统资源造成性能下降。

2.空连接较多,相当长时间并无数据传输占用系统资源,本人觉得这也许是所有BT软件的一个通病。

3. 请求和选择算法的设计上并不是很智能,难于产生所谓的Pareto Efficiency(帕累托效率)。

四、总结

一句话,Snark麻雀虽小五脏俱全,虽然诸多地方并不是很完美,但它提供了一个很好程序模型,便于我们更深入的了解p2p。

BT开源项目Snark源码分析相关推荐

  1. Go实现的5G核心网开源项目free5gc源码分析系列 | Gopher Daily (2021.01.08) ʕ◔ϖ◔ʔ

    每日一谚:"Abstractions should be discovered, not created." Go技术新闻 Go实现的5G核心网开源项目free5gc源码分析系列 ...

  2. 基于‘纯洁的微笑’开源项目 — Favorites 源码分析

    引言: 对于某语言不算熟悉的话自创项目是很痛苦的过程,即便笔者是一位掌握java的Android码农,对于java入门也是深感无力,毕竟语言是基础,但框架设计模式却与Android有出入,且学习成本较 ...

  3. go开源项目influxdb-relay源码分析(一)

    influxdb-relay项目地址: https://github.com/influxdata/influxdb-relay,主要作为负载均衡节点,写入多个influxdb节点,起到高可用效果. ...

  4. 今年我读了四个开源项目的源码,来分享下心得

    今年来看了 RocketMQ.Kafka.Dubbo .Tomcat 的源码,之前也有读者询问过如何读源码,索性就来分享一下. 其实还看了一点点 Linux.Redis.jdk8,这几个阅读的目的和上 ...

  5. 开源项目实例源码_今年我读了四个开源项目的源码,来分享下心得

    今年来看了 RocketMQ.Kafka.Dubbo .Tomcat 的源码,之前也有读者询问过如何读源码,索性就来分享一下. 其实还看了一点点 Linux.Redis.jdk8,这几个阅读的目的和上 ...

  6. 鸿蒙开源源码,基于鸿蒙系统开源项目OpenHarmony源码静态分析

    #ifndef __scc #define __scc(X) ((long) (X)) // 转为long类型 typedef long syscall_arg_t; #endif #define _ ...

  7. 【机器人学】机器人开源项目KDL源码学习:(5)KDL如何求解几何雅克比矩阵

    这篇文章试图说清楚两件事:1. 几何雅克比矩阵的本质:2. KDL如何求解机械臂的几何雅克比矩阵. 一.几何雅克比矩阵的本质 机械臂的关节空间的速度可以映射到执行器末端在操作空间的速度,这种映射可以通 ...

  8. 开源项目Telegram源码 Telegram for Android Source

    背景介绍 Telegram 是一款跨平台的即时通信软件,它的客户端是自由及开放源代码软件.用户可以相互交换加密与自毁消息,发送照片.影片等所有类型文件.官方提供手机版.桌面版和网页版等多种平台客户端. ...

  9. php,mysql 项目--商城--源码分析。

    php项目–商城–源码分析. 此商城网站源码下载地址:https://github.com/jeremywong1992/nuomi_shop php项目---商城--源码分析 网站目录下包含六个文件 ...

最新文章

  1. Spring读书笔记——bean创建(下)
  2. 可遇不可求的BUG之采用MYSQL odbc 3.51访问数据库返回值缺失
  3. 硬件服务器采购指南,硬件组装_服务器采购指南_太平洋电脑网PConline
  4. 利用Layer组件弹出多个对话框(非嵌套)与关闭及刷新
  5. C#中怎么判断一个数组中是否存在某个数组值
  6. 如何用python画饼图_Python中的五颜六色的饼状图!(一)
  7. 帝国cms数据库php调用tag,帝国CMS列表内容模板调用TAG的两种方法
  8. 设计模式的七大设计原则:其三:依赖倒转原则
  9. 5g理论速度_快看看 5G 的实际网速,失望还是兴奋?
  10. Ubuntu18.04图片信息查看器
  11. PyQt5的笔记(中-1)
  12. LPC1788 UART-DMA遇到的问题
  13. 7.STC15W408AS单片机串口通信
  14. Python numpy.ones函数方法的使用
  15. Windows下Jena+fuseki安装配置和简单使用(没有eclipse)
  16. 新版《鹿鼎记》史上最低分!数据分析告诉你,韦小宝跟哪个老婆最亲
  17. input获取焦点vue_在Vue中输入框自动获取焦点的三种方式
  18. 18V降压3.3V的降压IC和LDO芯片方案,15V降压3.3V的降压IC和LDO芯片方案
  19. Oracle 生僻字乱码问题
  20. 【黑灰产犯罪研究】涉物联网犯罪

热门文章

  1. 翻译Monoxide: Scale out Blockchains with Asynchronous Consensus Zones
  2. Java——检索一段话中出现次数最多的英文单词
  3. 【秒懂音视频开发】07_重识音频
  4. 企业微信小程序开发(行事历)
  5. 有赞+有赞云---需求分析
  6. 企业级容器技术docker(12)docker swarm
  7. Spark入门(三)——SparkRDD剖析(面试点)
  8. L1-021 重要的话说三遍 (5 分) 含解题思路 C语言
  9. 网页设计至少要掌握哪些技能
  10. es - elasticsearch - aggs - metrics - t-test