eliasson/pieces: An experimental BitTorrent client in Python 3.5 (github.com)
了解BitTorrent:BitTorrent 简介 - 知乎 (zhihu.com)
总结项目结构:
- pieces.py:启动程序,调用main()
- cli.py:main(),解析运行参数并生成
TorrentClient
并运行下载任务 - client.py:核心,实现
TorrentClient
,完成整个下载过程,主要实现访问tracker获取peer列表的过程。实现Block
和Piece
、PieceManager
,用于管理传输来的响应数据 - protocol.py:
PeerConnection
,用于对每个peer进行连接。PeerStreamIterator
异步解析字节流中BitTorrent协议信息。PeerMessage
,基类,派生类有Handshake
、KeepAlive
、BitField
、Interested
、NotInterested
、Choke
、Unchoke
、Have
、Request
、Piece
、Cancel
- tracker.py:封装tracker的响应信息,并实现连接tracker的方法
- torrent.py:使用BenCode处理种子文件
- becoding.py:实现BenCode的编解码
程序运行逻辑:
解析运行参数获得种子文件路径,处理种子文件获得tracker地址等信息,创建TorrentClient
,使用异步IO库asyncio
,创建TorrentClient.start()
为协程的任务,使用signal.signal()
处理中断信号,异步执行任务
loop = asyncio.get_event_loop()
client = TorrentClient(Torrent(args.torrent))
task = loop.create_task(client.start())
def signal_handler(*_):
logging.info('Exiting, please wait until everything is shutdown...')
client.stop()
task.cancel()
signal.signal(signal.SIGINT, signal_handler)
任务内容是构建容纳多个PeerConnection
的TorrentClient.peers
数组:这些连接(此时还不知道peer地址)会异步地监控available_peers
队列。然后进入死循环,根据默认间隔和之后tracker发来的呼叫间隔对tracker进行不断连接,从而实时更新available_peers
,直到检测到完成下载
async def start(self):
self.peers = [PeerConnection('''连接信息''')
for _ in range(MAX_PEER_CONNECTIONS)]
while True:
# 终止条件
current = time.time()
if (not previous) or (previous + interval < current):
# 与tacker连接
if response:
# 更新呼叫间隔(由tacker传回)
self