使用anacrolix/torrent库创建种子并做种失败问题排查
问题排查:anacrolix/torrent生成磁力链接后无法下载/获取元数据
问题描述
我想用Go语言的anacrolix/torrent库创建种子、生成磁力链接并做种,但运行代码后,生成的磁力链接既无法下载内容,也获取不到元数据,请帮忙排查代码中的遗漏点。
原代码
package main import ( "log" "time" "github.com/anacrolix/torrent" "github.com/anacrolix/torrent/bencode" "github.com/anacrolix/torrent/metainfo" ) var builtinAnnounceList = [][]string{ {"http://p4p.arenabg.com:1337/announce"}, {"udp://tracker.opentrackr.org:1337/announce"}, {"udp://tracker.openbittorrent.com:6969/announce"}, } func main() { tmpComment:="Cool torrent description" tmpCreatedBy:="coolboys" tmpInfoName:="CoolInfoName" mi := metainfo.MetaInfo{ AnnounceList: builtinAnnounceList, } mi.SetDefaults() mi.Comment = tmpComment mi.CreatedBy = tmpCreatedBy //} //mi.UrlList = args.Url//??????????? info := metainfo.Info{ PieceLength: 256 * 1024, } err := info.BuildFromFilePath("./TorrentFiles")//args.Root) if err != nil { log.Fatal(err) } info.Name =tmpInfoName mi.InfoBytes, err = bencode.Marshal(info) if err != nil { log.Fatal(err) } tmpMagnet:=mi.Magnet(nil,nil) log.Println("****",tmpMagnet) // cfg := torrent.NewDefaultClientConfig() cfg.Seed = true mainclient, ncerr := torrent.NewClient(cfg) if ncerr != nil { log.Println("new torrent client:", ncerr) return } defer mainclient.Close() t, _ := mainclient.AddMagnet(tmpMagnet.String()) for { log.Println("******", t.Seeding()) time.Sleep(8 * time.Second) } }
核心问题与修复方案
1. 错误使用磁力链接添加种子,未提供本地元数据
你当前通过AddMagnet将磁力链接添加到客户端,但此时客户端并没有本地的完整元数据,需要依赖tracker或DHT去获取——这个过程可能因为tracker失效、网络防火墙拦截等原因失败,导致无法获取元数据也无法做种。
正确做法:直接将本地生成的完整MetaInfo对象添加到客户端,而不是用磁力链接,这样客户端立刻拥有所有元数据,能直接开始做种。
2. Info.Name覆盖时机不当
你在info.BuildFromFilePath之后才设置info.Name,但BuildFromFilePath会根据传入的路径自动生成Name字段,后续覆盖可能导致元数据内部不一致(虽然影响较小,但建议提前设置)。
3. 缺少元数据加载等待逻辑(若坚持用AddMagnet)
如果一定要用磁力链接添加,必须等待客户端获取到元数据后再做种,否则服务根本无法正常启动。需要添加t.WaitForInfo()或监听t.GotInfo()通道。
4. 未显式启用DHT
默认配置可能未启用DHT,导致无法通过DHT网络获取元数据或连接对等节点,建议显式开启。
修正后的代码
package main import ( "log" "time" "github.com/anacrolix/torrent" "github.com/anacrolix/torrent/bencode" "github.com/anacrolix/torrent/metainfo" ) var builtinAnnounceList = [][]string{ {"http://p4p.arenabg.com:1337/announce"}, {"udp://tracker.opentrackr.org:1337/announce"}, {"udp://tracker.openbittorrent.com:6969/announce"}, } func main() { tmpComment := "Cool torrent description" tmpCreatedBy := "coolboys" tmpInfoName := "CoolInfoName" // 提前设置Info的Name,避免后续覆盖问题 info := metainfo.Info{ PieceLength: 256 * 1024, Name: tmpInfoName, } // 从本地路径构建文件信息 err := info.BuildFromFilePath("./TorrentFiles") if err != nil { log.Fatal(err) } // 构建完整的MetaInfo mi := metainfo.MetaInfo{ AnnounceList: builtinAnnounceList, Comment: tmpComment, CreatedBy: tmpCreatedBy, } mi.SetDefaults() // 序列化Info到MetaInfo mi.InfoBytes, err = bencode.Marshal(info) if err != nil { log.Fatal(err) } // 生成并打印磁力链接 tmpMagnet := mi.Magnet(nil, nil) log.Println("生成的磁力链接:", tmpMagnet) // 配置客户端,显式启用DHT cfg := torrent.NewDefaultClientConfig() cfg.Seed = true cfg.DHT = true cfg.DHTPort = 6881 mainclient, ncerr := torrent.NewClient(cfg) if ncerr != nil { log.Println("创建客户端失败:", ncerr) return } defer mainclient.Close() // 直接添加完整的MetaInfo,确保客户端拥有所有元数据 t, err := mainclient.AddTorrent(&mi) if err != nil { log.Println("添加种子失败:", err) return } // 等待种子元数据加载完成,确认可以开始做种 select { case <-t.GotInfo(): log.Println("种子准备完成,开始做种") case <-time.After(30 * time.Second): log.Println("等待种子准备超时") return } // 持续输出做种状态 for { log.Println("当前做种状态:", t.Seeding()) log.Println("已连接对等节点数:", len(t.Peers())) time.Sleep(8 * time.Second) } }
内容的提问来源于stack exchange,提问作者Andrea Jung
相关产品推荐
相关产品推荐

