跳转至

bep 23 紧凑 Tracker 响应

bep 23 原始链接

摘要

为了减少 tracker 响应的大小,和减少 tracker 的资源消耗,tracker 可以返回紧凑的响应

本文档中的 "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" 等关键词定义与 IETF RFC 2119 1 相同.

Overview

在 BEP 32 中定义了 tracker 如何响应 peers 的请求。This tracker returns a list of peers that are currently transferring the file. The list of peers is implemented as a list of bencoded dicts. Each dict in the list contains three fields: peer id, ip, and port. The peer id is 20 bytes plus 3 bytes bencoding overhead. The ip is a string containing a domain name or an IP address, and an integer port number. The ip is variable length, but since in its longest form it is a domain name it cannot exceed 255 bytes [2] plus 4 bytes bencoding overhead. Bencoded integers are also variable length but since it is a port number, it cannot be more than 7 bytes including bencoding overhead. Thus,

total peer list length in bytes < n * ( 23 + 259 + 7 )

现在 tracker 可以以一种更紧凑的方式进行响应,每个 ipv4 地址仅仅需要 6 字节。 前 4 字节表示 32-bit 的 ipv4 地址,后 2 字节表示端口数,字节和端口都使用网络字节顺,也就是大端序。

建议(SUGGESTED) tracker 默认返回紧凑响应。 客户端也可以在请求中添加 compact=0 来建议客户端优先使用原始格式(bep3 格式)进行响应, 也可以通过添加 compact=1 来建议 tracker 优先使用紧凑格式进行响应。

客户端的 compact 参数仅仅是建议性的,tracker 可以(MAY)任意选择一种格式, 客户端必需(MUST)同时支持两种响应。

例如:

GET /announce?peer_id=aaaaaaaaaaaaaaaaaaaa&info_hash=aaaaaaaaaaaaaaaaaaaa
&port=6881&left=0&downloaded=100&uploaded=0&compact=1

紧凑响应仍然使用 peers key,但是对应的值是二进制字符串,而非 bencode 列表。

紧凑响应不包括 peer id

例如:

import socket
import struct

from bencode2 import bdecode, bencode

packer = struct.Struct("!4sH")

# encode response

response = bencode({
    "interval": 3600,
    "peers": b"".join([
        packer.pack(socket.inet_aton(addr), ip)
        for addr, ip in [
            ("127.0.0.1", 50014),
            ("1.1.1.1", 49970),
        ]
    ]),
})

# decode response

peers = bdecode(response)[b"peers"]
for raw_addr, port in packer.iter_unpack(peers):
    print(socket.inet_ntoa(raw_addr), port)