我目前正在尝试使用 python 中的 libtorrent 构建一个 BitTorrent 客户端。由于我想通过 API 访问客户端,因此我从 libtorrent github 存储库(这是一个命令行工具)中获取了示例 client.py 并对其进行了修改。我的结果如下:
import libtorrent as lt
import time
import os.path
from loggers import logger
def add_torrent(ses, filename, save_path):
atp = lt.add_torrent_params()
ti = lt.torrent_info(filename)
# resume_file = os.path.join(save_path,
# ti.name() + '.fastresume')
# try:
# # Try to read resume file
# atp = lt.read_resume_data(open(resume_file, 'rb').read())
# except Exception as e:
# logger.exception(f"Failed to open resume file '{resume_file}': {str(e)}")
atp.ti = ti
atp.save_path = save_path
atp.storage_mode = lt.storage_mode_t.storage_mode_sparse
atp.flags |= lt.torrent_flags.duplicate_is_error \
| lt.torrent_flags.auto_managed \
| lt.torrent_flags.duplicate_is_error
ses.async_add_torrent(atp)
def add_suffix(val):
# Some parsing logic to get the right unit - see client.py, but should not be relevant
settings = {
'user_agent': 'python-client/' + lt.__version__,
'listen_interfaces': '127.0.0.5:6881',
'download_rate_limit': 0,
'upload_rate_limit': 10*1024*1024,
'alert_mask': lt.alert.category_t.all_categories,
'outgoing_interfaces': '',
}
ses = lt.session(settings)
# This throws an error!
#ses.add_dht_router()
torrents = {}
alerts_log = []
torrent_path = "/path/to/torrent/file/ubuntu-23.10.1-desktop-amd64.iso.torrent"
save_path = "/my/save/path/torrents/"
add_torrent(ses, torrent_path, save_path)
alive = True
while alive:
print(f"DHT enabled: {ses.is_dht_running()}")
print(f"DHT nodes: {ses.status().dht_nodes}")
for h, t in torrents.items():
if t.state != lt.torrent_status.seeding:
print(f"Error state: {t.error}")
print(f"Torrent status: {t.paused}")
print(f"Trackers: {h.trackers()}")
alerts = ses.pop_alerts()
for a in alerts:
alerts_log.append(a.message())
if isinstance(a, lt.add_torrent_alert):
h = a.handle
h.set_max_connections(60)
h.set_max_uploads(-1)
torrents[h] = h.status()
if isinstance(a, lt.state_update_alert):
for s in a.status:
torrents[s.handle] = s
if isinstance(a, lt.tracker_reply_alert):
print(f"Number of peers of tracker: {a.num_peers}")
if len(alerts_log) > 20:
alerts_log = alerts_log[-20:]
time.sleep(0.5)
ses.post_torrent_updates()
ses.pause()
for h, t in torrents.items():
if not h.is_valid() or not t.has_metadata:
continue
h.save_resume_data()
while len(torrents) > 0:
alerts = ses.pop_alerts()
for a in alerts:
if isinstance(a, lt.save_resume_data_alert):
print(a)
data = lt.write_resume_data_buf(a.params)
h = a.handle
if h in torrents:
open(
os.path.join(save_path,
torrents[h].name + '.fastresume'),
'wb').write(data)
del torrents[h]
if isinstance(a, lt.save_resume_data_failed_alert):
h = a.handle
if h in torrents:
print('failed to save resume data for ', torrents[h].name)
del torrents[h]
time.sleep(0.5)
我按照故障排除指南并在节点处结束:
DHT 可能无法正常工作。您可能想通过 session::add_dht_router() 添加 DHT 引导节点,或者有一个包含 DHT 节点的 torrent,或者属于 DHT 网络一部分的对等点的对等连接。
到目前为止我的脚本输出:
DHT enabled: True
DHT nodes: 0
Error state:
Torrent status: False
Trackers: [{'url': 'https://torrent.ubuntu.com/announce', 'trackerid': '', 'tier': 0, 'fail_limit': 0, 'source': 1, 'verified': False, 'message': '', 'last_error': {'value': 22, 'category': 'system'}, 'next_announce': 1706636536, 'min_announce': 1706636536, 'scrape_incomplete': -1, 'scrape_complete': -1, 'scrape_downloaded': -1, 'fails': 1, 'updating': False, 'start_sent': False, 'complete_sent': False, 'endpoints': [{'local_address': ('127.0.0.5', 6881), 'info_hashes': [{'message': '', 'last_error': {'value': 22, 'category': 'system'}, 'next_announce': 1706636536, 'min_announce': 1706636536, 'scrape_incomplete': -1, 'scrape_complete': -1, 'scrape_downloaded': -1, 'fails': 1, 'updating': False, 'start_sent': False, 'complete_sent': False}, {'message': '', 'last_error': {'value': 0, 'category': 'system'}, 'next_announce': 1706636536, 'min_announce': 1706636536, 'scrape_incomplete': -1, 'scrape_complete': -1, 'scrape_downloaded': -1, 'fails': 0, 'updating': False, 'start_sent': False, 'complete_sent': False}], 'message': '', 'last_error': {'value': 22, 'category': 'system'}, 'next_announce': 1706636536, 'min_announce': 1706636536, 'scrape_incomplete': -1, 'scrape_complete': -1, 'scrape_downloaded': -1, 'fails': 1, 'updating': False, 'start_sent': False, 'complete_sent': False}], 'send_stats': False}, {'url': 'https://ipv6.torrent.ubuntu.com/announce', 'trackerid': '', 'tier': 1, 'fail_limit': 0, 'source': 1, 'verified': False, 'message': '', 'last_error': {'value': 22, 'category': 'system'}, 'next_announce': 1706636536, 'min_announce': 1706636536, 'scrape_incomplete': -1, 'scrape_complete': -1, 'scrape_downloaded': -1, 'fails': 1, 'updating': False, 'start_sent': False, 'complete_sent': False, 'endpoints': [{'local_address': ('127.0.0.5', 6881), 'info_hashes': [{'message': '', 'last_error': {'value': 22, 'category': 'system'}, 'next_announce': 1706636536, 'min_announce': 1706636536, 'scrape_incomplete': -1, 'scrape_complete': -1, 'scrape_downloaded': -1, 'fails': 1, 'updating': False, 'start_sent': False, 'complete_sent': False}, {'message': '', 'last_error': {'value': 0, 'category': 'system'}, 'next_announce': 1706636536, 'min_announce': 1706636536, 'scrape_incomplete': -1, 'scrape_complete': -1, 'scrape_downloaded': -1, 'fails': 0, 'updating': False, 'start_sent': False, 'complete_sent': False}], 'message': '', 'last_error': {'value': 22, 'category': 'system'}, 'next_announce': 1706636536, 'min_announce': 1706636536, 'scrape_incomplete': -1, 'scrape_complete': -1, 'scrape_downloaded': -1, 'fails': 1, 'updating': False, 'start_sent': False, 'complete_sent': False}], 'send_stats': False}]
如您所见,tracker_reply_alert 不会被触发,因此我们没有任何“跟踪器对等点数量”的输出。然后我按照下一步尝试打电话给
ses.add_dht_router()
。但这会引发以下错误:
Boost.Python.ArgumentError: Python argument types in
session.add_dht_router(session)
did not match C++ signature:
add_dht_router(libtorrent::session {lvalue}, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > router, int port)
由于这是我第一次使用种子,我真的不知道我还可以尝试什么。如果有经验的人可以查看我的代码并可能为我指明正确的方向,我将非常高兴。预先谢谢您!
故障排除指南似乎已过时。
添加 dht bootstrap 节点的方法是通过设置包:
dht_bootstrap_nodes
https://libtorrent.org/reference-Settings.html#dht_bootstrap_nodes