golang BitTorrent客户端与库插件rain的使用

Golang BitTorrent客户端与库插件rain的使用

rain简介

Rain Logo

Rain是一个用Go语言编写的BitTorrent客户端和库。自2019年以来一直在put.io生产环境中运行,每天处理数千个种子。

功能特性

  • 核心协议
  • 快速扩展
  • Magnet链接
  • 多Tracker支持
  • UDP Tracker
  • DHT分布式哈希表
  • PEX对等交换
  • 消息流加密
  • WebSeed
  • 快速恢复
  • IP黑名单
  • RPC服务器和客户端
  • 控制台UI
  • 创建和读取.torrent文件的工具

安装

在MacOS上可以使用brew安装:

brew install cenkalti/rain/rain

其他系统可以从发布页面获取最新二进制文件。

作为Torrent客户端使用

Rain以单一二进制文件分发。主要使用方式是运行rain server命令,然后使用rain client <subcommand>命令操作服务器。服务器包含一个BitTorrent客户端和一个RPC服务器。

rain client用于向服务器发送命令。还有一个rain client console命令可以打开基于文本的UI,查看和管理服务器上的种子。运行rain help查看其他命令。

作为库使用

基本示例

import "github.com/cenkalti/rain/torrent"

// 创建会话
ses, _ := torrent.NewSession(torrent.DefaultConfig)

// 添加magnet链接
tor, _ := ses.AddURI(magnetLink, nil)

// 监视进度
for range time.Tick(time.Second) {
	s := tor.Stats()
	log.Printf("Status: %s, Downloaded: %d, Peers: %d", s.Status.String(), s.Bytes.Completed, s.Peers.Total)
}

完整示例

package main

import (
	"log"
	"time"

	"github.com/cenkalti/rain/torrent"
)

func main() {
	// 创建会话配置
	config := torrent.DefaultConfig
	config.DataDir = "./downloads" // 设置下载目录

	// 创建会话
	ses, err := torrent.NewSession(config)
	if err != nil {
		log.Fatal(err)
	}
	defer ses.Close()

	// 添加magnet链接
	magnetLink := "magnet:?xt=urn:btih:..."
	tor, err := ses.AddURI(magnetLink, nil)
	if err != nil {
		log.Fatal(err)
	}

	// 监听下载完成事件
	go func() {
		<-tor.NotifyComplete()
		log.Println("Download completed!")
	}()

	// 定期打印状态
	ticker := time.NewTicker(5 * time.Second)
	defer ticker.Stop()
	
	for range ticker.C {
		s := tor.Stats()
		log.Printf("Status: %s, Progress: %.2f%%, Downloaded: %d MB, Peers: %d",
			s.Status.String(),
			float64(s.Bytes.Completed)/float64(s.Bytes.Total)*100,
			s.Bytes.Completed/1024/1024,
			s.Peers.Total)
			
		if s.Status == torrent.Stopped {
			break
		}
	}
}

配置

所有值都有合理的默认值,因此您可以使用空配置运行Rain。但如果您想自定义其行为,可以使用-config标志传递YAML配置文件。配置键必须是小写的。

与其他客户端的区别

Rain是put.io使用的主要BitTorrent客户端。它设计用于处理数百个种子,同时使用较低的系统资源。与其他客户端的一个显著区别是Rain为每个种子使用单独的peer端口。这允许Rain为同一私有跟踪器中的多个帐户下载相同的种子,并保持其比例报告正确。

缺少的功能

以下功能未在Rain中实现:

  • IPv6 tracker扩展
  • DHT的IPv6扩展
  • uTorrent传输协议
  • 超级种子
  • HTTP种子
  • Merkle树种子扩展
  • uPnP端口转发
  • 选择性下载
  • 顺序下载

贡献

Rain主要是为满足put.io的特定需求而开发的。由于这一重点目的,与put.io需求不一致的功能请求可能会被拒绝。此外,我们强烈倾向于实现简单性 - 即使技术上更优越,复杂的解决方案通常也不会被接受。在提交问题或拉取请求时,请记住这些准则。


更多关于golang BitTorrent客户端与库插件rain的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang BitTorrent客户端与库插件rain的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


Golang BitTorrent客户端与rain库的使用

rain是一个用Go语言编写的轻量级BitTorrent客户端库,它提供了完整的BitTorrent协议实现,可以用于构建自定义的BitTorrent客户端或集成到其他应用中。

rain库简介

rain库的主要特点包括:

  • 纯Go实现,跨平台支持
  • 支持DHT网络
  • 支持磁力链接
  • 支持加密连接
  • 轻量级且易于集成

安装rain库

go get -u github.com/cenkalti/rain

基本使用示例

1. 最简单的下载示例

package main

import (
	"log"
	"time"

	"github.com/cenkalti/rain"
)

func main() {
	// 创建会话
	sess, err := rain.NewSession(rain.Config{
		DataDir:    "./downloads",
		Port:       6881,
		DisableDHT: false,
	})
	if err != nil {
		log.Fatal(err)
	}
	defer sess.Close()

	// 添加磁力链接
	torrent, err := sess.AddURI(
		"magnet:?xt=urn:btih:6a9759bffd5c0af65319979fb7832189f4f3c35d",
		nil,
	)
	if err != nil {
		log.Fatal(err)
	}

	// 等待下载完成
	for {
		stats := torrent.Stats()
		log.Printf("Progress: %.2f%%, Downloaded: %d, Uploaded: %d",
			stats.Progress*100, stats.BytesDownloaded, stats.BytesUploaded)

		if stats.Completed {
			log.Println("Download completed!")
			break
		}
		time.Sleep(time.Second)
	}
}

2. 更完整的客户端示例

package main

import (
	"fmt"
	"log"
	"os"
	"os/signal"
	"syscall"
	"time"

	"github.com/cenkalti/rain"
)

func main() {
	// 配置会话
	config := rain.Config{
		DataDir:           "./downloads",
		Port:              6881,
		DisableDHT:        false,
		DisableTCP:        false,
		DisableUTP:        false,
		DisableUpload:     false,
		DisableIPv6:       false,
		EncryptionPolicy:  rain.EncryptionPolicyPreferred,
		DownloadRateLimit: 0, // 0表示不限速
		UploadRateLimit:   0,
	}

	// 创建会话
	sess, err := rain.NewSession(config)
	if err != nil {
		log.Fatal(err)
	}
	defer sess.Close()

	// 处理命令行参数
	if len(os.Args) < 2 {
		log.Fatal("Usage: ./client <magnet-uri or torrent-file>")
	}
	source := os.Args[1]

	// 添加下载任务
	var torrent *rain.Torrent
	if _, err := os.Stat(source); err == nil {
		// 如果是文件
		torrent, err = sess.AddTorrentFile(source, nil)
	} else {
		// 如果是磁力链接
		torrent, err = sess.AddURI(source, nil)
	}
	if err != nil {
		log.Fatal(err)
	}

	// 打印基本信息
	fmt.Printf("Downloading: %s\n", torrent.Name())
	fmt.Printf("InfoHash: %s\n", torrent.InfoHash())

	// 设置信号处理,优雅退出
	sigCh := make(chan os.Signal, 1)
	signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM)

	// 进度监控循环
	ticker := time.NewTicker(3 * time.Second)
	defer ticker.Stop()

	for {
		select {
		case <-ticker.C:
			stats := torrent.Stats()
			fmt.Printf("\rProgress: %.2f%% | Peers: %d | ↓ %s/s | ↑ %s/s | Seeds: %d",
				stats.Progress*100,
				stats.ConnectedPeers,
				formatBytes(stats.SpeedDownload),
				formatBytes(stats.SpeedUpload),
				stats.AvailablePeers,
			)

			if stats.Completed {
				fmt.Println("\nDownload completed!")
				return
			}

		case <-sigCh:
			fmt.Println("\nShutting down...")
			return
		}
	}
}

// 格式化字节大小为易读格式
func formatBytes(bytes int64) string {
	const unit = 1024
	if bytes < unit {
		return fmt.Sprintf("%d B", bytes)
	}
	div, exp := int64(unit), 0
	for n := bytes / unit; n >= unit; n /= unit {
		div *= unit
		exp++
	}
	return fmt.Sprintf("%.1f %ciB", float64(bytes)/float64(div), "KMGTPE"[exp])
}

高级功能

1. 事件监听

// 添加事件监听器
sess.OnTorrentAdded = func(t *rain.Torrent) {
	log.Printf("Torrent added: %s", t.Name())
}

sess.OnTorrentRemoved = func(t *rain.Torrent) {
	log.Printf("Torrent removed: %s", t.Name())
}

sess.OnTorrentComplete = func(t *rain.Torrent) {
	log.Printf("Torrent completed: %s", t.Name())
}

2. 选择性下载文件

// 获取torrent文件列表
torrent, err := sess.AddURI(magnetURI, nil)
if err != nil {
    log.Fatal(err)
}

// 等待torrent信息加载完成
for torrent.Stats().Status != rain.StatusDownloadingMetadata {
    time.Sleep(time.Second)
}

// 获取文件列表并选择要下载的文件
files := torrent.Files()
for i, file := range files {
    fmt.Printf("%d: %s (%.2f MB)\n", i, file.Path, float64(file.Length)/1024/1024)
}

// 选择要下载的文件索引
var selected []int
// ... 根据用户输入设置selected

// 设置文件优先级
for i := range files {
    if contains(selected, i) {
        torrent.SetFilePriority(i, rain.PriorityNormal)
    } else {
        torrent.SetFilePriority(i, rain.PriorityNone)
    }
}

3. 保存和恢复会话

// 保存会话状态
err = sess.SaveSession()
if err != nil {
    log.Printf("Error saving session: %v", err)
}

// 在下次启动时自动恢复之前的下载任务
// 只需要在创建会话时指定相同的DataDir

注意事项

  1. 端口设置:BitTorrent客户端通常使用6881-6889端口,某些网络可能会阻止这些端口。

  2. DHT网络:DHT可以帮助在没有Tracker的情况下找到peer,但在某些网络环境下可能需要禁用。

  3. 速率限制:合理设置上传/下载速率限制,避免占用过多带宽。

  4. 磁盘空间:确保有足够的磁盘空间存放下载文件。

  5. 版权问题:确保下载的内容不侵犯版权。

rain库提供了丰富的配置选项和API,可以根据需要构建功能完善的BitTorrent客户端。以上示例展示了基本用法,更多高级功能可以参考官方文档和源代码。

回到顶部