torrent-go

module
v0.0.0-...-f0dcbf7 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 19, 2025 License: AGPL-3.0

README

Akimio521/torrent-go

一个使用 go-lang 编写的种子解析/下载库

简体中文 • English

概述

这个代码仓库包含了一个用 Go 语言实现的 BitTorrent 客户端库,支持种子文件解析、对等节点通信以及基于数据块的下载功能。该项目主要分为三个包:bencodetorrentcmd


功能特点

  • Bencode 编解码:对 Bencode 数据结构进行完整的编码和解码。
  • 种子文件解析:从 .torrent 文件中提取元数据和数据块哈希值。
  • 对端节点发现:向追踪服务器查询对等节点列表。
  • 并行下载:进行多数据块下载,并通过 SHA-1 进行验证。
  • 进度跟踪:通过 Context 实现实时的进度监控。

使用例子

file, _ := os.Open("example.torrent")  
tf, _ := torrent.ParseFile(file)
var peerId [torrent.PEER_ID_LEN]byte // radom Generate Peer ID
_, _ = rand.Read(peerId[:])
task, _ := tf.GetTask(peerID, 6881)
file.close()

file, err := os.Create(task.FileName)
if err != nil {
  fmt.Println("fail to create file: " + task.FileName)
  os.Exit(1)
}
defer file.Close()

if err = file.Truncate(int64(task.FileLen)); err != nil {
    fmt.Printf("fail to allocate disk space: %v\n", err)
    os.Exit(1)
}

ctx := task.Download()
for res := range ctx.GetResult() {
    begin, _ := task.GetPieceBounds(res.Index)
    if _, err := file.WriteAt(res.Data, int64(begin)); err != nil {
        fmt.Printf("fail to write piece %d: %v\n", res.Index, err)
        os.Exit(1)
    }
}

bencode

实现了 Bencode 编码/解码(BitTorrent 的数据序列化格式)。

核心组建:
  • BObject: bencode 存储基元,用于存储基本 bencode 对象或复杂 bencode 对象
    • func GetBObject[T allowedTypes](v T) *BObject: 用于生成 BObject 对象,保证 GetBObject 中值的合法性
    • func (o *BObject) GetBType() BType: 可以得到 BObject` 对象存储的类型
    • func GetValue[T allowedTypes](o *BObject, dest *T) error: 可以得到BObject 对象存储的值
    • func (o *BObject) Bencode(w io.Writer) (int, error): 将 BObject 编码写入 Writer 中,返回写入的字节长度
    • func Parse(r io.Reader) (*BObject, error): 从 io.Reader 中读取流并解析成 BObject 对象
  • 序列化与反序列化:
    • func Unmarshal(r io.Reader, s any) error: 从 io.Reader 读 bencode 数据绑定在数据结构上
    • func Marshal(w io.Writer, s any) (int, error): 将数据结构转换成 bencode 输出到 io.Wirter 中
  • 工具包、底层函数
    • func EncodeString(w io.Writer, val string) (int, error): 编码一个字符串写入 io.Writer
    • func DecodeString(r io.Reader) (string, error): 从 io.Reader 读数据并解码成字符串
    • func EncodeInt(w io.Writer, val int) (int, error): 编码一个整数写入 io.Writer
    • func DecodeInt(r io.Reader) (int, error): 从 io.Reader 读数据并解码成整数

torrent

处理种子文件解析、对端节点发现以及下载管理。

关键结构体
  • TorrentFile: 种子文件基本数据结构

    • func ParseFile(r io.Reader) (*TorrentFile, error): 传入一个 io.Reader 读取解析其中的种子文件信息
    • func (tf *TorrentFile) GetInfoSHA1() [sha1.Size]byte: 获得种子的 info 信息的 SHA-1 哈希值
    • func (tf *TorrentFile) GetAllPieceSHA() [][sha1.Size]byte: 获取所有的 SHA1 (使用 sha1.Size 分片存储方便分片下载后进行校验)
    • func (tf *TorrentFile) GetPiecesNum() int: 计算种子的分片数
    • func (tf *TorrentFile) GetTask(peerID [PEER_ID_LEN]byte, port uint16) (*TorrentTask, error): 传入本机的 PeerID 和 监听端口,自动向 tracker 查询 peer,返回一个 TorrentTask 对象
    • func (tf *TorrentFile) FindPeers(peerID [PEER_ID_LEN]byte, port uint16) ([]PeerInfo, error): 向 tracker 发起请求,查询 Peer
  • PeerInfo: 对端信息结构,包含对端 IP、监听端口

    • func (pi *PeerInfo) GetConnAddr() string: 获取对端的连接地址
  • TorrentTask: 种子下载任务

    • func (t *TorrentTask) GetPieceBounds(index int) (bengin int, end int): 根据分片的索引值计算分片的起始位置
    • func (task *TorrentTask) Download() *Context: 开始下载任务,返回一个 *Context
  • PieceTask: 分片下载任务,包含索引值,SHA-1 哈希校验值,分片长度信息

    • func (pt *PieceTask) CheckPiece(res *PieceResult) bool: 检查校验下载的分片内容是否匹配
  • PieceResult: 分片下载结构,包含索引值,下载数据

  • Context: 下载任务上下文

    • func (ctx *Context) Done() <-chan struct{}: 等待任务结束
    • func (ctx *Context) GetPeerInfos() []PeerInfo: 返回连接成功的对端 Peer 信息
    • func (ctx *Context) GetProcess() (uint64, uint64): 获取正在下载进度(已下载大小和已下载片数)
    • func (ctx *Context) GetResult() <-chan *PieceResult: 分片下载结果通道
    • func (ctx *Context) GetErr() <-chan error: 错误信息通道

cmd

一些简单的实例代码

Directories

Path Synopsis
cmd
download command
parse command

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL