You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

调试自定义Python libtorrent客户端:DHT路由添加报错及节点为0问题

问题解决:libtorrent DHT节点为0、tracker_reply_alert未触发及add_dht_router参数错误

问题概述

  • DHT已启用但节点数始终为0
  • tracker_reply_alert未触发,且tracker返回错误码22
  • 调用ses.add_dht_router()时出现Boost.Python参数不匹配错误

错误详情

调用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, std::allocator > router, int port)

当前脚本输出:

DHT enabled: True
DHT nodes: 0

问题分析与解决方案

1. add_dht_router参数错误

从错误信息可明确,add_dht_router()需要传入两个必填参数:引导节点地址和端口,你当前调用时未传参,导致参数不匹配。

正确调用方式示例:

# 添加官方DHT引导节点
ses.add_dht_router("router.bittorrent.com", 6881)
ses.add_dht_router("dht.transmissionbt.com", 6881)
ses.add_dht_router("router.utorrent.com", 6881)

2. DHT节点数为0的问题

  • 确保调用ses.start_dht()启动DHT服务(你的代码中未显式启动,默认可能未激活)
  • 添加引导节点后需等待一段时间,让节点完成发现与连接,不要立即检查节点数
  • 检查listen_interfaces配置:你使用的127.0.0.5:6881是本地回环地址,无法与外部DHT节点通信,建议改为0.0.0.0:6881或公网IP

修改后的session初始化示例:

settings = {
        'user_agent': 'python-client/' + lt.__version__,
        'listen_interfaces': '0.0.0.0: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)
# 启动DHT
ses.start_dht()
# 添加引导节点
ses.add_dht_router("router.bittorrent.com", 6881)
ses.add_dht_router("dht.transmissionbt.com", 6881)

3. tracker_reply_alert未触发及错误码22

错误码22对应libtorrent的invalid_argument,可能原因:

  • tracker地址无效或无法访问
  • 本地网络限制(防火墙、代理)导致无法连接tracker
  • 检查torrent文件中的tracker地址是否正确,或尝试添加公共tracker

另外,tracker_reply_alert仅在tracker成功返回时触发,连接失败会触发tracker_error_alert,建议添加该alert的处理逻辑:

if isinstance(a, lt.tracker_error_alert):
    print(f"Tracker error: {a.message()}, error code: {a.error.value()}")

完整修改后的代码

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

    ses.async_add_torrent(atp)


def add_suffix(val):
    # 单位解析逻辑参考client.py,此处不影响核心功能
    pass

settings = {
        'user_agent': 'python-client/' + lt.__version__,
        'listen_interfaces': '0.0.0.0: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)
# 启动DHT并添加引导节点
ses.start_dht()
ses.add_dht_router("router.bittorrent.com", 6881)
ses.add_dht_router("dht.transmissionbt.com", 6881)
ses.add_dht_router("router.utorrent.com", 6881)

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"Tracker返回节点数: {a.num_peers}")
        
        if isinstance(a, lt.tracker_error_alert):
            print(f"Tracker错误: {a.message()}, 错误码: {a.error.value()}")

        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:
                with open(
                    os.path.join(save_path,
                                 torrents[h].name + '.fastresume'),
                    'wb') as f:
                    f.write(data)
                del torrents[h]
        if isinstance(a, lt.save_resume_data_failed_alert):
            h = a.handle
            if h in torrents:
                print('保存续传数据失败: ', torrents[h].name)
                del torrents[h]
    time.sleep(0.5)

内容的提问来源于stack exchange,提问作者chocoloco

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 21:05:12