BT客户端实现 Peer协议设计

与peer创建tcp链接后,首先发送handshake消息进行握手python

handshake消息格式以下:多线程

一个字节0x19 + 一个字符串'BitTorrent protocol' + 8 byte 保留字节默认值为0(draft中对保留字节有定义)异步

+ 种子文件中info 部分的sha1字,大小为20个字节 + 20个本身的peer id(从tracker获取到的peer信息大多没有peerid,这个可使用本地的peer id)socket

若是handshake信息协商不上,tcp链接将被关闭。tcp

 

BT标准BEP-3中定义了8种peer消息:消息格式为msg_len(4个字节) + msg_type(1一个字节) + payload函数

0 - choke  --发送该消息表示本段发送阻塞,对端将不能获取到piece数据,payload 为 0性能

1 - unchoke  --发送该消息表示解阻塞,对端能够开始发送请求获取piece数据,payload 为 0线程

2 - interested  --发送该消息,表示对对端的pieces数据有兴趣,payload 为 0设计

3 - not interested  ---发送该消息,表示对对端的pieces数据没有兴趣了,payload 为 0rest

4 - have       ---发送该消息,通告对端 本段拥有的pieces,payload为4个字节的piece index

5 - bitfield  ---发送该消息,通告对端 本段拥有的pieces,为bit map的方式表示每一个piece index在本端是否拥有。piece index所在bit位为1,表示拥有。

                     该消息为handshake成功后的第一个消息。

6 - request   ---piece请求消息,payload为: index, begin, and length,都是4个字节表示,length通常实现为0x8000, 最大不能超过0x20000。

7 - piece     ---piece  数据,payload为: index, begin,data 

8 - cancel    ---发送该消息,表示本端取消了某个piece请求。payload为:index, begin, and length

 

使用python的异步socket接口实现,为了减小处理过程被socket阻塞,使用多个线程处理每一个peer。

每一个peer包括3个线程:request timeout timer ,socket send data thread, socket receive data thread,使用select 函数判断socket是否可读、可写。

对socket读写操做时使用RLock进行保护,select阻塞进程时不加锁,避免阻塞其余线程。

发送数据数据时先写一个队列,而后经过set threading.Event 变量出发socket send data thread发送数据,保证发送数据的线程不阻塞

因为 python没有结束线程的接口,socket send data thread, socket receive data thread 须要依赖特殊变量的赋值,使socket处理进程结束。

使用同步调用来触发下载过程运转,尽可能不使用timer轮询的方式,能够下降cpu使用率并加快下载过程。

可是,多线程间的同步调用因为锁的存在,会致使性能降低并容易引入信号量死锁的问题。须要仔细设计好多线程的运行轨迹避免死锁。

draft BEP中定义的功能暂未实现,peer的上传流控未实现,peer质量分级未实现。

相关文章
相关标签/搜索