1.结点状态,结点对每个连接保存了四个布尔值:
amchoking:对方被阻塞
aminteresting:对对方感兴趣
amchoked:被对方阻塞
aminterested:对方对自己感兴趣
2.数据块结构
BT系统中目标文件被分成256KB的小块,便于在结点之间交换。实际上,这些数据块又被分为子块,一般一块为16KB,结点之间传送的是16KB的子块,这样可以更好的利用带宽。结点在某一块内可以按任意顺序下载子块,但是不会跨块下载不同块内的子块,这是因为整块数据需要用摘要验证正确性,而只有验证正确的数据才能提供给其他结点下载,为了尽快共享整块数据,就应该尽量把一整块下载完整,再下载其他的块。块在整个目标文件中是按顺序排列的,每个块都有编号,结点之间使用数据块编号来定位数据块,每一块都有对应的摘要,存储在Torrent文件中:而子块是用在块中相对于块头的偏移和子块数据的长度来定位的,称为子块偏移和子块长度。
3.结点间传输的消息
结点之间开始传输数据之前,有一个握手过程,这个过程可以过滤掉非BT程序的误连。握手过程中双方互相发送一个TCP包,内容如下所示:
Pstrlen(1)
|
Pstr(19)
|
Reserved(8)
|
Info_hash(20)
|
Peer_id(20)
|
其中psrt是一个字符串“BiTTorrent portocol”,prstlen是psrt的长度,也就是19;reserved是留给扩展协议用的,一般都是0;info_hash与发给追踪器的info_hash是相同的,peer_id也与发给追踪器的peer_id相同(其他结点从追踪器得到的对应的peer_id与这个值相同)。经过握手之后,两个结点之间就可以开始互相发送消息了,可发送的消息格式有10种,格式如下表:
name
|
Lengthprefix(4)
|
Messageid(1)
|
Payload
|
Keep alive
|
0000
|
无
|
无
|
Choke
|
0001
|
0
|
无
|
Unchoke
|
0001
|
1
|
无
|
Interested
|
0001
|
2
|
无
|
Not interested
|
0001
|
3
|
无
|
Have
|
0005
|
4
|
1个整数
|
Bitfield
|
不定
|
5
|
不定长
|
Request
|
000D
|
6
|
3个整数
|
Piece
|
不定
|
7
|
不定长
|
Cancel
|
000D
|
8
|
3个整数
|
其中length prefix是一个4位的整数,表示后面的message ID与payload的总长度;message ID是消息号,长度固定为1位,payload是负载,存储其他信息,长度不定。消息可按照长度分为3类,第一类为空消息,也称为keep alive消息,空消息没有消息号和负载。结点发送空消息的目的是保证对方依然在线。如果对方在线,会回发一个TCP头上带ACK标志的空消息;第二类是通知消息,只有消息号,没有负载,消息长度固定为1。通知消息包括消息号为0-3的4种消息,结点通过这几个消息通知对方设置阻塞和感兴趣两个值。第三类是数据消息,剩下的5种消息都是属于这一类,这些消息负责结点之间的数据传输。
(1)have消息
结点在下载某一块数据结束时,向所有己连接的结点发送have消息,通知其他结点自己已经有这块数据,可以提供下载,have消息的负载是数据块的编号。
(2)bitfield消息
在握手之后,如果结点己经有部分数据,那么向对方发送bitfield消息来描述己有数据,bitfield消息只能在握手之后,所有其他消息发送前发送。不过bitfield消息是可以省略的,如果结点没有任何数据,可以不发送bitfield消息。bifield消息的负载描述了该结点己有的数据,第一个字节的最高位表示第一块数据,也就是编号为0的数据块,后面每一位表示下一块数据。如果某一位为0,表示结点没有对应的数据块,如果某一位为1,表示结点己经有对应的数据块。如果最后的字节不满8位,剩下的位用0填充。
(3)request消息
结点要从某结点下载数据时,向这个结点发送request消息。request消息的负载是三个整数,分别是数据块编号、子块在数据块内的偏移、以及子块长度。
(4)piece消息
piece消息进行实际的数据传输。结点要回应request消息,就发送piece消息。piece消息的负载是数据块编号、子块偏移以及子块内容。
(5)cancel消息
cancel消息是在“结束模式”下发送的,“结束模式”中结点向所有结点发送request消息请求下载某子块,当子块下载完成时,就不需要从其他结点再下载这一子块了,结点给其他所有结点发送cancel消息,通知其他结点不用发送子块。cancel消息的负载与have消息完全相同,数据块编号、子块偏移、子块长度。
分享到:
相关推荐
通信结点就是任何与移动结点相通信的结点,它可以是静止的,也可以是移动的。移动结点能够通知通信结点自己的当前位置,这个动作通过通信绑定过程来完成。当向任一个IPv6目的地发送数据包时,结点必须在自己的绑定...
链表与数组不同,不依赖于物理位置的连续性,而是通过节点间的引用连接彼此。本篇文章将深入探讨单循环链表的概念、特点以及如何实现带头结点和不带头结点的两种情况。 1. **单循环链表的基本概念** - **链表**:...
共享内存协议允许节点间快速访问数据,而半用户级协议则关注系统的安全性、可靠性和可移植性,同时支持异构网络环境。 文章详细探讨了共享内存协议的不同实现方式和优化策略,以提高通信性能。这些策略可能包括缓存...
统计复杂网络中2-4个结点间具有相同最短距离的点的对数。该程序中使用的复杂网络来源于该开源数据集: http://vlado.fmf.uni-lj.si/pub/networks/data/Ucinet/bkoff.dat 这个数据集是一个40×40的矩阵。在这个网络...
采用先序法建立一棵二叉树,设计输出某结点数据为x的双亲结点的数据的程序,二叉树的数据域类型为字符型, 扩展二叉树的叶子结点用‘#’表示,要求可以求一棵二叉树中多个结点的双亲。
计算图中两两结点路数为m的邻接矩阵,计算图中两两结点路数为m的邻接矩阵
编写算法交换二叉树中所有结点的左右子树 本文档主要介绍了如何编写算法交换二叉树中所有结点的左右子树。该算法使用 C 语言实现,通过建立二叉树、先序遍历输出结点数据和后序遍历交换左右子树三个步骤来实现。 ...
该例子已经通过验证,是一个可以运行的例子。同时还包含了两个子网之间的通信。
二叉树上结点的路径 二叉树是一种重要的数据结构,它在计算机科学和信息技术领域中具有广泛的应用。本文将对二叉树上结点的路径进行详细的介绍和分析。 一、什么是二叉树? 二叉树是一种特殊的树形结构,它的每个...
判别结点u是否为结点v的子孙
AB通信协议 AB通信协议是一种工业自动化领域广泛应用的通信协议,主要用于AB PLC(Programmable Logic Controller)与上位机之间的数据交换。该协议支持RockwellAutomation公司的MicroLogix、SLC及部分PLC-X系列PLC...
链表是一种动态的数据结构,它由一系列结点组成,每个结点都包含一个值和指向下一个结点的指针。链表的优点是可以动态地添加或删除结点,从而实现灵活的数据管理。 头结点的作用 ------------- 在链表中,头结点是...
二叉树叶子结点个数计算 本文档讨论了二叉树叶子结点个数计算的问题,涵盖了二叉树的存储结构、递归算法设计、实现提示、源程序等方面。 一、存储结构 在计算二叉树叶子结点个数时,我们需要首先设计二叉树的存储...
### 只有尾结点的链表表示的队列算法 #### 1. 定义结点和队列结构 本篇文章将介绍一种利用链表实现队列的方法,该方法的特点在于只维护一个指向链表尾部(即队列尾部)的指针。这种方法在某些场景下可以有效地减少...
用C++简单实现无头结点的建表,插入,删除操作
根据提供的文档内容,我们可以总结出以下关于使用带头结点的循环链表表示队列的数据结构算法知识点: ### 1. 循环链表定义及队列表示 #### 结点类型定义 ```c typedef int Datatype; // 定义数据类型 typedef ...
在循环链表中,由于最后一个结点指向头结点,所以删除最后一个结点时需要特别处理,将头结点的next指针设置为当前链表的第二个结点,以保持链表的循环性。 **出列过程**是按照一定的规则进行的。在经典的约瑟夫环...
二叉树的指定结点路径 二叉树是一种常见的数据结构,它有广泛的应用,如文件系统、数据库、浏览器的历史记录等。在二叉树中,每个结点最多有两个孩子结点,即左孩子和右孩子。二叉树可以分为满二叉树、完全二叉树和...
要求控制台显示如下内容,然后根据前方数字进行相应操作 1、创建一条含整数结点的无序链表 2、链表结点的输出 3、链表结点的升序排序 4、分别计算链表中奇数和偶数结点之和并输出 5、释放链表 0、退出
从根结点到指定结点的路径 ——二叉树遍历法 随着社会科技的发展,人类的生活水平的提高。然而,在发展的同时,我们也不能避免选择,在十字路口,我们可能会有多种选项,由这些不同的路口,我们都能达到相同的目的地...