P2P 您所在的位置:网站首页 choking和choked的区别 P2P

P2P

2023-05-26 13:59| 来源: 网络整理| 查看: 265

对端管理

指的是远端peer集合的管理(尽管自身client也能够视为一个peer。但对端管理不包括自身peer)

一个client(client)必须维持与每一个远程peer连接的状态信息,即1V1关系(本端对某个远端peer)

在本代码中PcPeer指这样的1V1关系,而不是仅指远程peer

对于每一个连接连接来说。每一端的peer应该是4种状态之中的一个:一端是interested或者not interested。则还有一端是choking或者unchoking。反之亦然。Choking表示直到unchoking发生之前,都不会有不论什么数据传送给连接还有一端的peer

代码例如以下:

#define CPE_STAT_NONE ((char)0x00)#define CPE_STAT_LC_I ((char)0x01) //B 是否拥有 A 感兴趣的分片#define CPE_STAT_RM_I ((char)0x02) //A 是否拥有 B 感兴趣的分片#define CPE_STAT_LC_C ((char)0x04) //A 是否能向 B 请求分片数据#define CPE_STAT_RM_C ((char)0x08) //B 是否能向 A 请求分片数据

这些信息由例如以下关键字来描写叙述:

choke(拒绝/阻塞)、unchoke(接受)两种状态 假设远程peer对本client是choke,远程peer将不会接收来自本client的请求 而本client在接收到来自远程peer的choke消息后,就不会再试图向远程peer发送数据请求,由于本client会觉得全部发给远程peer的请求都已被丢弃

interest(兴趣) 远程peer是否对本client提供的数据感兴趣。这由远程peer通知本client,当本client不choke它时,远程peer就開始请求块(block),这也意味着 本代码中PcPeer须要记录本client是否对远程peer感兴趣。以及它是否choke/unchoke远程peer

client连接開始时的初始状态为choke和not interstered(不感兴趣)

当本client对远程peer感兴趣,而且该远程peer没有choke时。那么本client就能够从远程peer下载块(block)

当本client没有choke远程peer,而且该远程peer对本client感兴趣时,本client就会上传块(block)

这也就意味着,在建立连接后,本client必须不断的通知远程peer。告诉远程peer。是否对它还感兴趣

本和远程peer的状态信息必须保持最新。即使本client被choke,这样才干保证,当远程peer不再choke本client时,本client能够開始下载(反之亦然)

对端通信协议

对端之间要进行通信。须要使用P2P通信协议

本代码位于

bool CPcPeer::pack(char *pack, int &len, HOSTHANDLE& addr)bool CPcPeer::unpack(char *pack, const int len)

P2P协议的消息类型例如以下:

// 下述为0x0f下的#define P2P_CONTROL_INV ((char)0x01) //连接请求#define P2P_CONTROL_PAV ((char)0x02) //连接响应#define P2P_CONTROL_CMD ((char)0x03) //命令#define P2P_CONTROL_DAT ((char)0x04) //数据#define P2P_CONTROL_LIV ((char)0x05) //心跳// 下述为0xf0下的#define P2P_MASK_CHK ((char)0x80) //CHOKE标记掩码#define P2P_MASK_REQ ((char)0x40) //REQUEST标记掩码#define P2P_MASK_HAV ((char)0x20) //HAVE标记掩码

PcPeer的step状态为

enum {ST_NONE, ST_PEND, ST_LINK, ST_TRAN};

初始本client和远程peer均为ST_NONE状态

step状态的转换图例如以下:

P2P-BT对端管理协议(附BT协议1.0)_上传

1.本client发送连接请求报文后。本client状态更新为ST_PEND

远程peer收到连接请求协议后,远程peer的状态更新为ST_LINK

2.远程peer发送连接请求回复协议,远程peer的状态更新为ST_TRAN

3.本client收到远端peer发回的连接回复协议,本client状态由ST_PEND更新为ST_TRAN

4.此后本client和远端peer状态均为ST_TRAN

协议流程图例如以下:

P2P-BT对端管理协议(附BT协议1.0)_数据_02

P2P-BT对端管理协议(附BT协议1.0)_#define_03

P2P-BT对端管理协议(附BT协议1.0)_数据_04

任务文件http:serve的地址列表info_hash:任务文件中info部分的sha校验码。即公布的种子数据peer_id:自身的标识port:提供上传的port号ip:你的ip地址,没有的话serve会自己找到uploaded、dowloaded:你上传和下载了多少,server能够用它做流量分析left:还要下载多少字节event:状态,告诉服务端你是准备開始下载,还是停止,或下载完毕了 BT在打开一个任务文件后,先选择文件保存在哪里,然后推断文件不存在的话就建立新文件,存在的话就用sha-1去校验文件,假设校验错误。说明是未下载的文件,就能够实现续传server服务端会使用info_hash查找列表。同一时候。依据ip和port进行反向连接。以測试用户是内网用户还是公网用户(假设是内网用户。是无法连通的)服务端的返回信息中,有一个时间參数。用来告诉client用户隔多少时间一次服务端。由于BT的动态性非常高。1秒内,可能有成千的peer添加或退出,所以须要一个參数设置查询频率分片选择算法

严格的优先级

第一个策略是。一旦请求了某个分片的子片段,然后该分片余下的子片段会优先被请求,这样,能够尽可能获得一个完整的分片

最少优先

对一个下载者来说。选择下一个被下载分片时,通常选择它的peer们所拥有的最少的那个分片,即最少优先。这样的技术。确保了每一个peer都拥有其它peer们最希望得到的那些片段,从而一旦有须要,上传就能够開始

随机的第一个片段

最少优先的一个例外是下载開始时。此时,下载者没有不论什么分片可供上传。所以需尽快获得一个完整的分片。所以,第一个分片是随机选择的,直到第一个分片下载完毕。才切换回最少优先的策略

最后阶段模式

有时候,peer可能从一个速率非常慢的peer那里请求一个分片,为了防止这样的情况,在最后阶段,peer向全部的peer都发送某分片的子片段请求,一旦某些子片段到了,就向其它的peers发送取消消息,取消对这些子片段的请求。以避免带宽浪费

请求的并发发送

在BT中。非常重要的一点是同一时候发送多个请求,以避免单个请求的两个片段发送之间的延迟

peer发送到serve的请求info_hash: 即种子hashpeer_id:使用URL编码的20字节串。用于标识client的唯一ID,由client启动时生成。这个ID能够是随意值,甚至可能是二进制数据。眼下没有生成该ID的标准准则,尽管如此。实现者必须保证该ID对于本地主机是唯一的,因此能够通过包括进程ID和启动时记录的时间戳(timestamp)来达到这个目的port:client正在监听的port号。为BitTorrent协议保留的port号是6881-6889uploaded:peer已上传的总量(从start事件開始)downloaded:peer已下载的总量(从start事件開始)left:client还未下载的字节数。以十进制表示compact:设置为1,表示client接收压缩的响应包,这时peers列表将被peers串替换,peers串中每一个peer占6个字节(前4表示ip,后2表示port)numwant(可选):client希望从serve接受的peers数,如未设置,默觉得50ip(可选):client的IP地址。仅仅有当请求的IP地址不是client的IP地址时。才须要此參数(client通过代理的方式交互)key:当clientip改变时,可用该标识来证明自己的身份event:假设指定,必须是started/completed/stoped和空之中的一个,假设一个请求不指定event,表示它仅仅是每隔一段时间发送的请求,event取值例如以下started:第一个发送到serve的请求,其event必须为此值stopped:假设正常关闭client,必须发该事件到servecompleted: 假设下载完毕。必须发送该事件到serve。假设client启动前,就已完毕下载,则不是必需发送,serve仅仅基于此事件添加已完毕的下载数 event指定了值,但值为空,那么它和event不指定值的效果一样(定期发送)serve回复peer的请求failure reason:假设包括这个键(key)。那么其它的键(key)就不会出现,该键(key)相应的值是一个可读的错误消息,它告诉用户的请求为什么会失败interval:指定peer间隔发送请求的时间min interval(可选):最小的请求间隔,表示peer不能在这个时间间隔内向track重发请求complete:完毕整个文件下载的peers数(做种数)incomplete:未完毕文件下载的peers数(非做种数)peers:peers列表

peer列表数一般控制在30-55之间,当一个分片下载完毕后,client须要将have消息发送给大部分活跃的peers。结果是广播通信的代价和peers数目成正比,当这个数高于25以后,新添加的peers已不太可能提升下载速度

Peer端交互

一个client(client)必须维持其与每一个远程peer(端)连接的状态信息:

choked: 远程peer(端)是否已经choke本client。当一个peer(端) choke本client后。它是在通知本client。除非它unchoke本client。否则它不会应答该client所发出的不论什么请求。本client也不应该试图向远程peer发送数据请求。而且应该觉得全部没有应答的请求已经被远程peer丢弃。interested: 远程peer(端)是否对本client提供的数据感兴趣。这是远程peer在通知本client。当本clientunchoke他们时,远程client将開始请求块(block)。 注意这也意味着本client须要记录它是否对远程peer(端)感兴趣。以及它是否choke/unchoke远程peer。

因此真正的列表看起来像这样:

am_choking: 本client正在choke远程peeram_interested: 本client对远程peer感兴趣peer_choking: 远程peer正choke本clientpeer_interested: 远程peer对本client感兴趣。

client连接開始时状态是choke和not interested(不感兴趣)。换句话就是: l am_choking = 1 l am_interested = 0 l peer_choking = 1 l peer_interested = 0 当一个client对一个远程peer感兴趣而且那个远程peer没有choke这个client。那么这个client就能够从远程peer下载块(block)。当一个client没有choke一个peer,而且那个peer对这个client这个感兴趣时,这个client就会上传块(block)。

client必须不断通知它的peers,它是否对它们感兴趣,这一点是非常重要的。client和每一个端的状态信息必须保持最新。即使本client被choke。这同意全部的peer知道。当它们unchoke该client后。该client是否開始下载(反之亦然)。

握手

握手是一个必需的报文。而且必须是client发送的第一个报文。该握手报文的长度是(49+len(pstr))字节

握手的消息格式:​​handshake: ​​

pstrlen: 的字符串长度。单个字节。

pstr: 协议的标识符,字符串类型。

reserved: 8个保留字节。当前的全部实现都使用全0.这些字节里面的每一个字节都能够用来改变协议的行为。

info_hash: 种子hashpeer_id: 用于唯一标识client的20字节字符串。 连接的发起者应该马上发送握手报文。一旦接收方看到握手报文中的info_hash部分,接收方必须尽快响应 假设一个client接收到一个握手报文。而且该client没有服务这个报文的info_hash,那么该client必须丢弃该连接。 假设一个连接发起者接收到一个握手报文,而且该报文中peer_id与期望的peer_id不匹配,那么连接发起者应该丢弃该连接报文

接下来协议的全部报文採用例如以下的结构:​​​​。

length prefix(长度前缀)是一个4字节的大端(big-endian)值。message ID是单个十进制值。playload与消息相关。

keep-alive

格式 :​​​​

keep-alive消息是一个0字节的消息,将length prefix设置成0。没有message ID和payload。假设peers在一个固定时间段内没有收到不论什么报文(keep-alive或其它不论什么报文),那么peers应该关掉这个连接。因此假设在一个给定的时间内没有发出不论什么命令的话,peers必须发送一个keep-alive报文保持这个连接激活。通常情况下。这个时间是2分钟

choke

格式 :​​​​

choke报文长度固定,而且没有payload。

unchoke

格式 :​​​​

unchoke报文长度固定。而且没有payload。

interested

格式 :​​​​

interested报文长度固定,而且没有payload。

not interested

格式 :​​​​

not interested报文长度固定,而且没有payload。

have

格式 :​​​​

have报文长度固定。payload是piece(片)的从零開始的索引。该片已经成功下载而且通过hash校验。

实现者注意:实际上,一些client必须严格实现该定义。由于peers不太可能下载他们已经拥有的piece(片),一个peer不应该通知还有一个peer它拥有一个piece(片),假设还有一个peer拥有这个piece(片)。最低限度”HAVE suppresion”会使用have报文数量减半。总的来说,大致降低25-35%的HAVE报文。同一时候,给一个拥有piece(片)的peer发送HAVE报文是值得的,由于这有助于决定哪个piece是稀缺的。 一个恶意的peer可能向其它的peer广播它们不可能下载的piece(片)。

bitfield

格式 : ​​​​

bitfield报文可能仅在握手序列发送之后。其它消息发送之前马上发送。

它是可选的,假设一个client没有piece(片),就不须要发送该报文。

bitfield报文长度可变。当中x是bitfield的长度。

payload是一个bitfield,该bitfield表示已经成功下载的piece(片)。

第一个字节的高位相当于piece索引0。设置为0的位表示一个没有的piece,设置为1的位表示有效的和可用的piece。末尾的冗余位设置为0。

长度不正确的bitfield将被觉得是一个错误。假设client接收到长度不正确的bitfield或者bitfield有任一冗余位集,它应该丢弃这个连接。

request

格式 : ​​​​

request报文长度固定,用于请求一个块(block)。payload包括例如以下信息:

index: 整数,指定从零開始的piece索引。begin: 整数,指定piece中从零開始的字节偏移。length: 整数。指定请求的长度。piece

格式 :​​​​

piece报文长度可变,当中x是块的长度。payload包括例如以下信息:

1. index: 整数,指定从零開始的piece索引。

2. begin: 整数,指定piece中从零開始的字节偏移。

3. block: 数据块,它是由索引指定的piece的子集。

cancel

格式 :​​ 0x1001 -> 9)

固定的消息头之后是8个字节长的保留字节,眼下的实现里是全0。假设你希望利用这些保留自己进行功能扩充。请与Bram Cohen协商以确保全部的扩展是兼容的。

接着便是元信息文件中面info的SHA1哈希值,长度为20个字节。(这和发送给Trackerserver的request里面的info_hash基本是一样的,唯一的差别是这里就是SHA1哈希值,而info_hash还须要进行escape处理)(注:由于发送Trackerserver的request是用HTTP的GET方式传送的,所以必须进行escape处理。而这里是直接TCP连接,用的是BT自己的协议。所以不须要escape处理)。假设两方发送的值不一样。则切断连接(注:假设hash值不一样。则表示下载的不是同一个文件。也就不是必需继续了。所以这里应该是要断开连接的)。有一个例外就是假设某个BTclient希望通过一个port下载多个文件,那么它能够先等对方发送info的hash值,接收后,假设自己的下载列表里包括该文件,那么发送给对方相同的info的hash值就能够了(注:假设没有,则等同于两方hash值不一样,能够直接断开连接)。

info的hash值传输完之后是20byte的peer id。

每一个下载端的peer id在向Trackerserver发送request时被Trackerserver记录下来,同一时候包括在Trackerserver发送给BTclient的response里面的peer id列表里。所以假设接受方回应的peer id和期待的peer id不一样,就切断连接。

(注:具体解释下:開始下载时。会向Trackerserver依照前面所述各式发送request。接着从Trackerserver的response里,能够获得一系列[ip,peer id],那么通过ip地址和对方连接后,依照本协议。对方会发送它的peer id过来,假设它发来的peer id和从Trackerserver上获得的不一样,就切断连接。)

以上就是握手的过程,接下来就是带有长度前缀的消息流(注:以bencoded方式编码的消息流)。

长度为0的消息时用作保持连接(注:相似于心跳帧)。不会做进一步的处理。心跳消息通常每2分钟发送一次(注:也就是说,当没有实用的传输数据时,超时时间大约是2分钟),可是当发送数据消息时,超时可能会发生的更快(注:叶就是说超时时间可能会短的多)。

全部的非心跳消息以一个单字节开头,该字节用来定义消息类型。

可选的消息类型例如以下:

0 - choke

1 - unchoke

2 - interested

3 - not interested

4 - have

5 - bitfield

6 - request

7 - piece

8 - cancel

‘choke’, ‘unchoke’, ‘interested’, 和 ‘not interested’没有负载(注:也就是说没有具体的消息内容。由于消息类型就已经表达了全部的内容)。

‘bitfield’必须是握手之后的第一个消息,假设须要发送的话(注:由于该消息是可选的)。它的内容表明了发送方peer已经拥有了哪些文件块:拥有的文件块的序号所相应的bit设置为1。没有的设置为0。假设没有不论什么文件块,则能够跳过该消息(注:也就是不发送)’。bitfield’的第一个字节从高位到低位依次代表文件块0到7。第二个字节代表8到15,其余依次类推。结尾多余的bit设置为0。(注:举例来说假设一个文件被分为20块,某个peer開始下载时已经有了第1,4,7,18块,那么它发送的’bitfield’消息的内容就应该是010010010000000000100000)。

‘have’消息的内容是一个数字:刚刚下载完毕而且正确的通过hash值验证的文件块的序号(注:该消息用于通知连接那一头的peer)。

‘request’消的内容包括一个序号。開始位置和长度。位置和长度的单位是字节。长度一般是2的幂,除非由于到达文件末尾。当前的实现使用的值是2的15次幂(注:即32KB。这是最早的值,现行版本号的BT用的值请參考文章开头注明的另外一遍更具体的文档)。假设对方peer要求的值大于2的17次幂(注:即128KB)则断开连接。

(注:文件块并非在一次消息中全然被传输,实际上文件块又被细分为更小的块,为了说明方便,这里称之为cell。所以通常下载完一个文件块须要多个request消息,每一个request消息用来要求对方传输某个指定的cell。

request消息中的序号知名是哪个文件块,開始位置能够理解为cell的序号,长度是固定值。能够理解为cell的大小)。

‘cancel’ 消息的内容和request消息的内容一样。’cancel’ 消息通常仅仅在文件下载到最后的时候才有可能被发送。这一时期消息发送/处理方式被称为”游戏结束模式”。

当文件下载将近尾声时,通常都有这样的趋势:最后的少量数据会从某个单通道的modem线路上获得(注:”off a single hosed modem line”不知道怎样翻译好),而且速度会非常的慢。所以为了尽快取得最后的这些数据块。一旦要求这些数据块的requests准备好了,就会把这些requests发给全部正在向我发送数据的peer(要求他们发送我须要的数据块)。为了避免数据重发而导致的效率低下(注:这里的数据重发指的是不同的peer都会向我发送相同的数据),一旦我得到了某个数据块,我就向其它全部peer发送cancel消息。告诉它们我已经得到了某个数据块,不须要再向我发送了。

‘piece’消息的内容包括序号。開始和具体的数据。尽管消息的内容里没有明白说明,但该消息实际上是和request消息相关的(注:能够理解为该消息就是request消息的response消息,要来传输request消息中要求的文件数据)。须要注意的是有时候会收到非期望的’piece’消息,比方choke和unchoke这两个消息交替发生的太快,或者消息传输的太慢。

文件块的下载顺序一般是随机的。这样能够避免某个peer拥有的文件块是和它相连的peer的超集或者子集。从而使下载合理并有效。

Choking之所以存在有几个理由:首先是由于向很多连接同一时候发送数据的时候。TCP的阻塞控制做的非常差(所以BTclient须要自己做Choking,也就是阻塞,目的说白了就是要提高下载效率)。另外choking也让每一个peer採用一种轮回的算法以保证它们能够达到一致的下载速度(注:事实上就是通过choking控制,避免和自己相连的某些peer下载速度快。而其它peer则一直非常慢,简而言之,就是为了公平)。

下面描写叙述的choking算法是当前已经应用的一个。

非常重要的一点是:全部新的算法既要能在全部由新算法构成的BT网络里工作。也要能在大多数BTclient使用的是老算法的网络里工作。

一个好的算法应该达到下面几个标准。它应当能够限制一定数量的上传连接以获得好的TCP性能。它应该避免频繁的在choking和unchoking之间切换,这被叫做”纤维性颤动”。

它应当报答那些让它下载的peer(注:也就是不要choking下载源)。

最后,它应当时不时地尝试那些未曾unchoking过的peer(注:由于初始状态是choking。),以便能够找到比当前已经连接的效果更好的peer,这被称作乐观地unchoking。

当前实际应用的算法通过延迟10秒去改变某个peer的choking状态。以避免”纤维性颤动”。通过unchoking四个下载速度最好,而且是自己interested的peer。来报答这些peer和限制上传连接。同一时候,上传速度好,但不是interested的peer会被unchoking。可是假设它们变成interested状态,那么上传速度最差的peer会被choking。假设自己拥有完整的文件(注:自己是种子)。那么就用上传速度来决定谁应该被unchoke。

最佳畅通是指:一直都会有一个peer被unchoking而无论它的上传速度(假设它是自己interested。那么就作为4个被同意的下载者之中的一个)。最佳畅通每30秒循环一次。

为了让他们有机会下载一个完整的文件块(注:指某些最佳畅通的peer下载了某个文件块的一部分之后被choking了,为了能让他们下载完这个文件块),下次和它的建立连接的可能性将会是循环中其它普通的畅通的三倍(注:即30秒后,要再次进行最佳畅通时,该peer被选中的可能性将会3倍于其它peer。

假设这样的peer多于一个,那么它们之间的竞争则应该是平等的)。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有