BitTorrent 协议规范(BT协议集合)二三

BT4.0协议规范.zip BT4.0协议规范文档,详细描述了4.0协议层、测试场景、测试规范等,对于BT有兴趣和疑问的尽量从协议下手 立即下载
概要
     上一节我们分析了BT客户端与tracker之间的通信过程。通过与 tracker 的通信,客户端获得了参与下载的其它peers 的列表。有了这些 peers 的信息,客户端就可以主动向它们发起连接,为进一步从它们那里获取所需要的文件片断做好准备。这些连接称为“主动连接”。因为连接的发起方是客户端自己。
     同时,每个客户端在启动以后,都会监听某个端口,用于接受其它 peers 的连接请求。P2P的核心理念就是“公平、对等”,你向别人有所求(下载),就必须有付出(上传)。客户端在接受外来的连接请求之后,就会产生一个新的连接,称之为“被动连接”,因为连接的发起方是其它 peer。
     无论是被动连接,还是主动连接,一旦连接建立之后,双方就要进行“BT对等协议”的握手。握手成功之后,双方才可以通过这个连接互相传递消息了。为什么要进行握手了?主要目的是为了防止一些错误的连接。这就好比地下党接头,暗号对上了,彼此才建立信任。

















     在这个示意图中,客户端 A 与 其它 peers B、C、D、E 都建立了连接。通过箭头来表示连接建立的方向。A主动与 B、D、E 建立连接;A被动接收C的连接。同时C与D、E与D、B与D之间也都有连接。这样,所有下载者之间就形成了一个网状的结构。
     同时,这些下载者都要与 tracker 之间不断通信。
     无论是被动连接,还是主动连接,一旦在“BT对等握手”成功之后,它们就没有任何区别了。下载通过这个连接进行,上传也是通过这个连接进行。
    
     本文重点分析BT客户端如何主动向其它 peers 发起连接;BT客户端如何被动接收其它 peers 的连接请求;以及在连接建立成功之后,如何进行BT对等协议握手的过程。

      客户端主动发起连接
【Encrypter.py】
     上一节的最后,我们看到调用 Encoder::start_connection() 来向其它 peer 发起连接。所以,从这里开始看起。

class Encoder:
# start_connection() 需要两个参数:
dns:对方的ip、port 的组合。
id: 对方的 id。每个BT客户端都要创建一个唯一的 id 号,并且把这个 id 号报告给 tracker。Id号唯一标识了一个客户端。Id 号的计算方式在 download.py 中。
myid = 'M' + version.replace('.', '-')
myid = myid + ('-' * (8 - len(myid))) + b2a_hex(sha(repr(time()) + ' ' +
str(getpid())).digest()[-6:])
seed(myid)
①def start_connection(self, dns, id):
    if id:
        # 如果 id 是自己,不连接
        if id == self.my_id:
          return
        # 如果已经和这个peer建立了连接,也不再建立连接。
        for v in self.connections.values():
          if v.id == id:
return
           # 如果当前连接数过多,暂时不发起连接
    if len(self.connections) >= self.max_initiate:
# self.spares 起到缓存的作用。在当前连接数过多的情况下,把本次要连接的 peer 的 ip、port 缓存起来。一旦当前连接数小于设定值 max_initiate, 则可以从 spares 中取出备用的 peers。
        if len(self.spares) < self.max_initiate and dns not in self.spares:
          self.spares.append(dns)
        return
    try:
# 调用 RawServer::start_connection(),发起 TCP 的连接。RawServer的代码分析请参看“服务器源码分析”系列文章,不再赘述
# 返回的 c 是一个 SingleSocket 对象,它封装了 socket 句柄
        # 如果出错,抛出 socketerror 异常
        c = self.raw_server.start_connection(dns)
# 成功建立 TCP 连接。构造一个 Connection对象,加入 connections 字典中。注意,最后一个参数是 True,它表面这条连接是由客户端主动发起建立的。我们立刻去看 Connection 类的构造
        self.connections[c] = Connection(self, c, id, True)
    except socketerror:
        pass

【Encrypter.py】
class Connection:
② def __init__(self, Encoder, connection, id, is_local):
    self.encoder = Encoder
    self.connection = connection #这个 connection 是 SingleSocket 对象,就是上面 RawServer::start_connection() 返回的值,它封装了对socket句柄的操作。名字起的不好,容易弄混淆。
    self.id = id
    self.locally_initiated = is_local #这个连接是否由本地发起?
    self.complete = False
    self.closed = False
    self.buffer = StringIO()
    self.next_len = 1
    ⑦self.next_func = self.read_header_len
          
# 如果由本地发起,那么给对方发送BT对等连接的握手消息。
    ④if self.locally_initiated:
        connection.write(chr(len(protocol_name)) + protocol_name +
          (chr(0) * 8) + self.encoder.download_id)
        if self.id is not None:
          connection.write(self.encoder.my_id)

      客户端被动接受外来连接
客户端在与 tracker 通信的时候,已经把自己的 ip 和监听的 port 报告给了 tracker。这样,其它 peers 就可以通过这个 ip 和 port 来连接它了。例如上图中的C,就主动给 A 发一个连接,从C的角度来说,它是“主动连接”,但从A的角度,它是“被动连接”。
一旦有外来连接请求,就会调用 RawServer::handle_events(),下面是摘录的“Tracker 服务器源码分析之二:RawServer类”中的一段。



















最后调用的是 Handle 的 external_connection_made(),对客户端来说,这个Handle 是 Encoder 类对象。所以,外来连接建立成功后,最后调用的是 Encoder:: external_connection_made():

③def external_connection_made(self, connection):
     # 同样是创建一个新的 Connection 类,并加入 connections 字典中。但不同之处在于最后一个参数是 False,表明这个连接是由外部发起的。
self.connections[connection] = Connection(self, connection, None, False)

      BT对等连接握手:第一步

如果是主动连接,那么一旦连接建立成功之后,就给对方发送一个握手消息,我们折回去看序号为 4 的代码:
if self.locally_initiated:
       connection.write(chr(len(protocol_name)) + protocol_name +
          (chr(0) * 8) + self.encoder.download_id)
    if self.id is not None:
       connection.write(self.encoder.my_id)

在《BT协议规范》中,如此描述握手消息:
对等协议由一个握手开始,后面是循环的消息流,每个消息的前面,都有一个数字来表示消息的长度。握手的过程首先是先发送19,然后发送协议名称“BitTorrent protocol”。19就是“BitTorrent protocol”的长度。
后续的所有的整数,都采用big-endian 来编码为4个字节。
在协议名称之后,是8个保留的字节,这些字节当前都设置为0。
接下来对元文件中的 info 信息,通过 sha1 计算后得到的 hash值,20个字节长。接收消息方,也会对 info 进行一个 hash 运算,如果这两个结果不一样,那么说明双方要下载的文件不一致,会切断连接。
接下来是20个字节的 peer id。
可以看到,最后两项就是 Encoder::download_id 和 Encoder::my_id。download_id是如何得来的?它是首先对 torrent 文件中 info 关键字所包含的信息进行 Bencoding 方式的编码(请看《BT协议规范》关于 Bencoding的介绍),然后再通过 sha 函数计算出的 hash(摘要)值。(相关代码都在 download.py 中)。在一次下载过程中,所有的下载者根据 torrent 文件计算出的这个 download_id应该都是一样的,否则就说明不处于同一个下载过程中。
至于 peer_id,可以看出是可选的。它的计算方式也在 download.py 中:
myid = 'M' + version.replace('.', '-')
myid = myid + ('-' * (8 - len(myid))) + b2a_hex(sha(repr(time()) + ' ' + str(getpid())).digest()[-6:])
seed(myid)

它用来唯一标识一个 peer。
握手过程已经完成了第一步,还需要第二步,接收到对方的握手消息,握手过程才算完成。所以接下去看在有数据到来的时候,是如何处理的。

      BT对等连接握手:第二步
当TCP连接上有数据到来的时候, RawServer 会调用到 Encoder:: data_came_in()

【Encoder】
⑤def data_came_in(self, connection, data):
    self.connections[connection].data_came_in(data)

进一步调用 Connection::data_came_in()

【Connection】
⑥def data_came_in(self, s):
     #这个循环处理用来对BT对等连接中的消息进行分析
    while True:
        if self.closed:
          return
        i = self.next_len - self.buffer.tell()
        if i > len(s):
          self.buffer.write(s)
          return
        self.buffer.write(s[:i])
        s = s[i:]
        m = self.buffer.getvalue()
        self.buffer.reset()
        self.buffer.truncate()
        try:
          x = self.next_func(m) #调用消息分析函数,第一个被调用的是read_header_len
        except:
          self.next_len, self.next_func = 1, self.read_dead
          raise
        if x is None:
          self.close()
          return
        self.next_len, self.next_func = x

⑧def read_header_len(self, s):
     # 协议的长度是否为 19?
    if ord(s) != len(protocol_name):
        return None
    return len(protocol_name), self.read_header # 下一个处理函数

def read_header(self, s):
     # 协议名称是否是“BitTorrent protocol”?
    if s != protocol_name:
        return None
    return 8, self.read_reserved # 下一个处理函数

def read_reserved(self, s):
     #8个保留字节
    return 20, self.read_download_id # 下一个处理函数

def read_download_id(self, s):
     对方 download_id 和自己计算出的是否一致?
    if s != self.encoder.download_id:
return None
           检查完 download_id,就认为对方已经通过检查了。
这里很关键!!!,需要仔细体会。这实际上就是在被动连接情况下,完成握手过程的处理。如果连接不是由本地发起的(被动接收到一个握手消息),那么给对方回一个握手消息。这里的握手消息发送处理和第一步是一样的
    if not self.locally_initiated:
        self.connection.write(chr(len(protocol_name)) + protocol_name +
          (chr(0) * 8) + self.encoder.download_id + self.encoder.my_id)
    return 20, self.read_peer_id #下一个处理函数

def read_peer_id(self, s):
# Connection 类用来管理一个 BT 对等连接。在握手完成之后,就用对方的 peer_id 来唯一标识这个 Connection。这个值被保存在 self.id 中。显然,在握手完成之前,这个 id 还是空值。
    if not self.id:
                 # 对方的peer_id 可千万别跟自己的一样
        if s == self.encoder.my_id:
          return None
                 唔,如果 peer_id 已经收到过,也不继续下去了
        for v in self.encoder.connections.values():
          if s and v.id == s:
return None
                 用对方的 peer_id 为 self.id 赋值,唯一标识这个 Connection
        self.id = s
        if self.locally_initiated:
          self.connection.write(self.encoder.my_id)
        else:
          self.encoder.everinc = True
    else:
                
                 if s != self.id:
          return None
           # OK,握手完成!!!
    self.complete = True
    self.encoder.connecter.connection_made(self)
    return 4, self.read_len #下一个处理函数。从此以后,就是对其它BT对等消息的处理过程了。这是我们下一节分析的问题。

      小结:
     这篇文章重点分析了BT客户端主动发起连接和被动接收连接的过程,以及在这两种情况下,如何进行BT对等握手的处理。
     在BT对等握手完成之后,连接的双方就可以互相发送BT对等消息了,这是下一节的内容。 
蓝牙4.0核心规范 蓝牙4.0核心规范 蓝牙4.0为蓝牙3.0的升级标准 蓝牙4.0最重要的特性是省电科技,极低的运行和待机功耗可以使一粒纽扣电池连续工作数年之久。此外,低成本和跨厂商互操作性,3毫秒低延迟、100米以上超长距离、AES-128加密等诸多特色,可以用于计步器、心律监视器、智能仪表、传感器物联网等众多领域,大大扩展蓝牙技术的应用范围。 立即下载

相关推荐

常用的最新BT协议规范说明文档

包括AVRCP_v1.6.2、A2DP_v1.3.2、FTP_v1.3.1、HFP_v1.7.2、HID_v1.1.1、Mesh Device Properties v1.0、PBAP_v1.2.3、3DSP_v1.0.3

客户端源码分析之八:BT对等连接的建立过程

客户端源码分析之八:BT对等连接的建立过程作者:小马哥日期:2005-01-09rstevens2008 At hotmail.com版权所有,未经允许,不得转载转载请注明出处: http://www.wlm.com.cn/openidea/leobbs.cgi概要 上一节我们分析了BT客户端与tracker之间的通信过程。通过与 tracker 的通信,客户端获得了参与下载的其它peers

5174

工创赛智能搬运小车实战:视觉定位、底盘控制与RTOS调度

智能搬运系统是嵌入式控制与机器视觉融合的典型工程实践,其核心在于视觉定位精度、运动控制稳定性与实时任务调度能力。在有限算力(如STM32H7)、低功耗约束和结构化场景下,传统CV方法(如FAST+RANSAC)比轻量级深度学习更具鲁棒性与实时性;而底盘控制需穿透PID表层,直击死区补偿、编码器硬件滤波与负载自适应等物理层细节;RTOS则不是炫技工具,而是保障多模块时序确定性的刚需——尤其在视觉-控制-执行强耦合链路中,任务优先级、事件组通信与栈安全直接影响系统存活。本文聚焦全国大学生工程训练竞赛(工创赛)真

weixin_29194693的博客 267

BT Protocol 规范1.0

BitTorrent 协议规范1.0版 2007-11-15 11:25 摘自http://wiki.theory.org /BitTorrentSpecification,标题为Bittorrent Protocol Specification v1.0。它

Walter的专栏 1768

[OHIF-Viewers]医疗数字阅片-医学影像-cornerstone-core-Cornerstone.js-Cornerstone Examples-基石实例-下...

[OHIF-Viewers]医疗数字阅片-医学影像-cornerstone-core-Cornerstone.js-Cornerstone Examples-基石实例-下 CT Image with Window presets This is an example of displaying a ct image along with buttons to set ww/wc pres...

浩秦的博客 1841

PCB线路板的制作工艺流程分享!2021-08-21

Pcb板制作工艺流程:开料-钻孔-沉铜-压膜-曝光-显影-电铜-电锡-退膜-蚀刻-退锡-光学检测-印阻焊油-阻焊曝光、显影-字符-表面处理-成型-电测-终检-抽测-包装。具体如下:1、开料(CUT) 将原始的覆铜板切割成可以用在生产线上制作的板子过程2、钻孔 使PCB板层间产生通孔,以达到连通层间的目的。 3、沉铜 经过钻孔后的线路板在沉铜缸内会发生氧化还原反应,形成铜层对孔进行孔金属化,使原来绝缘的基材表面沉积上铜,达到层间电性相通。 4、压膜 压膜后的PCB板上面压了一层蓝色的干膜, 干膜是一个载体

jdbpcb88的博客 3246

BT协议集合

BT协议集合2008-02-25 18:20BitTorrent 协议规范(BT协议集合)一 BitTorrent 是一种分发文件的协议。它通过URL来识别内容,并且可以无缝的和web进行交互。它基于HTTP协议,它的优势是:如果有多个下载者并发的下载同一个文件,那么,每个下载者也同时为其它下载者上传文件,这样,文件源可以支持大量的用户进行下载,而只带来适当的负载的增长

Lixinag的专栏 1893

大模型量化技术全解析:从INT8到GPTQ/AWQ,降低部署成本实战指南

模型量化是一种通过降低神经网络权重和激活值的数据精度(如从FP16降至INT8/INT4),从而大幅减少模型内存占用和计算开销的核心模型压缩技术。其原理基于线性变换,将高精度浮点数映射到低精度整数表示,在硬件层面能利用专用低精度计算单元实现显著加速。这项技术的核心价值在于解决了大模型(如千亿参数LLM)部署时面临的高昂显存成本和推理延迟问题,使其能在消费级GPU和边缘设备上高效运行。当前,后训练量化(PTQ)因其无需重新训练的特性成为主流,衍生出GPTQ、AWQ、SmoothQuant等多种方法,广泛应用于

weixin_33804582的博客 630

BitTorrent 协议规范(BT协议集合)十二

作者:小马哥 概述: 相对于 tracker 服务器来说,BT客户端要复杂的多,Bram Cohen 花了一年 full time 的时间来完成 BT,我估计其中大部分时间是用在 BT 客户端的实现和调试上了。 由于 BT 客户端涉及的代码比较多,我不能再象分析 tracker 服务器那样,走上来就深入到细节之中去,那样的话,我写的晕晕糊糊,大家看起来也不知所云。所以第一篇文章先来谈谈客户端的功能

1037

Win10环境借助DockerDesktop部署Open web UI集成DeepSeek

Win10环境借助DockerDesktop部署Open web UI集成DeepSeek,并借助DuckDuckGo实现联网查询

虎鲸不是鱼 1699

数字蓝牙功放

数字蓝牙功放(TPA3110+BK8000L),基于D类数字功放芯片TPA3116蓝牙功放,HIFI级带滤波15Wx2蓝牙数字功放,支持有线和蓝牙两种音源输入

runweipa的博客 1419

BitTorrent 协议规范(BT协议集合)二二

昨天重新读了BT协议和客户端代码,发现对协议本身部分比较熟悉了,但是对BT在实际运行期间各种行为的发生情景还非常模糊,有些步骤还想清楚,大家一起来讨论一下. 我们来一起描述一下BT各种消息的发送情景. 有些不是特别肯定的我没有加上,大家在这个基础上进行增加或者修改. 其中client指本机上运行的BT客户端.peer指tracker返回的远程客户端. piece指torrent文件中的20byte

1297

CMU动作捕捉数据集实战:从AMC文件到Python可视化的完整流程

本文提供了CMU动作捕捉数据集的完整实战指南,详细解析了AMC文件格式,并对比了MATLAB转换、Python原生解析及转换为BVH格式三种数据解析策略。重点介绍了如何构建Python数据处理与可视化管道,包括将数据转换为Pandas DataFrame、绘制时间序列与相关性热力图,以及实现3D骨架动画,帮助开发者高效利用这一经典动作捕获数据集进行运动分析与模型训练。

android的专栏 716

BitTorrent 协议规范(BT协议集合)三

Bittorrent udp-tracker protocol extension Contents introduction connecting Client sends packet: Server replies with packet: announcing Client sends packet: Server replies with packet: scraping Client

1029

ASProxy64.dll导致jetbrains家的IDE都无法打开。

摘要:在Windows11系统中,JetBrains IDE无法启动,报错指向ASProxy64.dll文件。该第三方DLL被注入到JVM原生层,导致内存访问冲突(错误代码0xc0000005)。经排查发现此文件来自Astrill软件。解决方案为卸载Astrill后重启电脑,问题得以解决。该案例表明第三方DLL注入可能影响IDE正常运行,卸载相关软件是最直接的解决方法。(149字)

猿小白的博客 936

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

BitTorrent 协议规范(BT协议集合)二四

BitTorrent是一个优秀的P2P下载软件,国内又叫它BT(变态)。 BT的主页:http://bitconjurer.org/BitTorrent/index.html BT的作者:Bram Cohen,《程序员》杂志2004第3期有对他的介绍文章 BT所用的语言:python python:一种优秀的动态语言(关于动态语言的介绍,看《程序员》杂志2004年第5期)。 python的官方网站

1541

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

BitTorrent 协议规范(BT协议集合)十八

客户端源码分析之六:客户端的主程序 作者:小马哥 前言: 自从7月份写完“客户端源码分析之五:Encoder 与 Connection 类”后,我就停止了继续对BT源码的分析。原因很多,最主要的还是懒惰吧。临到岁末,终于下定决心,无论如何,要完成这一系列的文章,对自己也算有个交待。 前面的几篇文章,都是深入到源码的某一部分细节之中,虽然很清晰,但无助于读者对整体构架的把握(其实我自己当时也比较糊涂

926

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

BitTorrent 协议规范(BT协议集合)

BitTorrent 协议规范(BT协议集合)翻译:小马哥 日期:2004-5-22 BitTorrent 是一种分发文件的协议。它通过URL来识别内容,并且可以无缝的和web进行交互。它基于HTTP协议,它的优势是:如果有多个下载者并发的下载同一个文件,那么,每个下载者也同时为其它下载者上传文件,这样,文件源可以支持大量的用户进行下载,而只带来适当的负载的增长。(译注:因为大量的负载被均衡到整个

gogl的专栏 1875

BitTorrent 协议规范(BT协议集合)二

这个翻译版本由孤波独立完成 原文见http://bitconjurer.org/BitTorrent/protocol.html 作者Bram Cohen 孤波享有对该翻译版本解释权修改权 非商业引用请注明译者 BitTorrent协议详解 BitTrrent(简称BT,比特洪流)是一个文件分发协议,它通过URL识别内容并且和网络无缝结合。它在HTTP平台上的优势在于,同时下在一个文件的下载者在下

1043

BitTorrent 协议规范(BT协议集合)一

BitTorrent 是一种分发文件的协议。它通过URL来识别内容,并且可以无缝的和web进行交互。它基于HTTP协议,它的优势是:如果有多个下载者并发的下载同一个文件,那么,每个下载者也同时为其它下载者上传文件,这样,文件源可以支持大量的用户进行下载,而只带来适当的负载的增长。(译注:因为大量的负载被均衡到整个系统中,所以提供源文件的机器的负载只有少量增长) 一个BT文件分布系统由下列实体组成:

1026

BitTorrent 协议规范(BT协议集合)十七

Encoder 是一种 Handler 类(关于 Handler类,请参看前面的分析文章)。它在 download.py 中被初始化。它与 Connection类一起,完成“BT对等连接”的建立,以及“BT对等协议”的分析。 为了有助于理解,我添加了一些用圆圈括起来的序号,建议你按照这个顺序去阅读。 class Connection:   ②def __init__(self, Encoder,

929

BitTorrent 协议规范(BT协议集合)九

Tracker服务器源码分析之一:总述 作者:小马哥 日期:2004-5-29   tracker服务器是BT下载中必须的角色。一个BT client 在下载开始以及下载进行的过程中,要不停的与 tracker 服务器进行通信,以报告自己的信息,并获取其它下载client的信息。这种通信是通过 HTTP 协议进行的,又被称为 tracker HTTP 协议,它的过程是这样的:   client 向

1320

BitTorrent 协议规范(BT协议集合)二十

作者:小马哥 本篇文章分析 Tracker 类,它在 track.py 文件中。 在分析之前,我们把前几篇文章的内容再回顾一下,以理清思路。 BT的源码,主要可以分为两个部分,一部分用来实现 tracker 服务器,另一部分用来实现BT的客户端。我们这个系列的文章围绕 tracker 服务器的实现来展开。 BT 客户端与 tracker 服务器之间,通过 track HTTP协议进行通信,而BT客

1057

BitTorrent 协议规范(BT协议集合)十九

客户端源码分析之七:客户端与tracker通信过程4VM 作者:小马哥 l概要 上一节我们分析了BT客户端主程序的框架:一个循环的服务器程序。在这个循环过程中,客户端要完成如下任务:l Ø与 tracker 服务器通信;汇报自己的状态,同时获取其它 peers 的信息;. Ø接受其它 peers 的连接请求;a%dv Ø主动向某些 peers 发起连接请求;8 Ø对BT对等协议的分析处理;kn Ø

1259

BitTorrent 协议规范(BT协议集合)二一

 BT客户端开始一个下载首先要处理的就是torrent文件. 而torrent文件使用bencoding编码. 所以实现bencoding编码的解析器,就是第一步工作. Bencoding is done as follows: Strings are length-prefixed base ten followed by a colon and the string. For e xample

987
上一篇: BitTorrent 协议规范(BT协议集合)二二
下一篇: BitTorrent 协议规范(BT协议集合)二四
Pregunta
博客等级 码龄23年 6粉丝 19原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值