【p2p、分布式,区块链笔记 Torrent】WebTorrent的add和seed函数

  • 在【p2p、分布式,区块链笔记 Torrent】WebTorrent的上传和下载界面的示例中,主要通过WebTorrent类的add和seed函数实现相关功能。这两个函数都返回一个Torrent类对象的实例。

seed函数

import createTorrent, { parseInput } from 'create-torrent' // "create-torrent": "^6.0.18"/*** Start seeding a new file/folder.* @param  {string|File|FileList|Buffer|Array.<string|File|Buffer>} input* @param  {Object=} opts* @param  {function=} onseed called when torrent is seeding*/seed (input, opts, onseed) {if (this.destroyed) throw new Error('client is destroyed')if (typeof opts === 'function') [opts, onseed] = [{}, opts]this._debug('seed')opts = opts ? Object.assign({}, opts) : {}// no need to verify the hashes we createopts.skipVerify = trueconst isFilePath = typeof input === 'string'// When seeding from fs path, initialize store from that path to avoid a copyif (isFilePath) opts.path = path.dirname(input)if (!opts.createdBy) opts.createdBy = `WebTorrent/${VERSION_STR}`const onTorrent = torrent => {const tasks = [cb => {// when a filesystem path is specified or the store is preloaded, files are already in the FS storeif (isFilePath || opts.preloadedStore) return cb()torrent.load(streams, cb)}]if (this.dht) {tasks.push(cb => {torrent.once('dhtAnnounce', cb)})}parallel(tasks, err => {if (this.destroyed) returnif (err) return torrent._destroy(err)_onseed(torrent)})}const _onseed = torrent => {this._debug('on seed')if (typeof onseed === 'function') onseed(torrent)torrent.emit('seed')this.emit('seed', torrent)}const torrent = this.add(null, opts, onTorrent)let streamsif (isFileList(input)) input = Array.from(input)else if (!Array.isArray(input)) input = [input]parallel(input.map(item => async cb => {if (!opts.preloadedStore && isReadable(item)) {const chunks = []try {for await (const chunk of item) {chunks.push(chunk)}} catch (err) {return cb(err)}const buf = concat(chunks)buf.name = item.namecb(null, buf)} else {cb(null, item)}}), (err, input) => {if (this.destroyed) returnif (err) return torrent._destroy(err)parseInput(input, opts, (err, files) => {if (this.destroyed) returnif (err) return torrent._destroy(err)streams = files.map(file => file.getStream)createTorrent(input, opts, async (err, torrentBuf) => {if (this.destroyed) returnif (err) return torrent._destroy(err)const existingTorrent = await this.get(torrentBuf)if (existingTorrent) {console.warn('A torrent with the same id is already being seeded')torrent._destroy()if (typeof onseed === 'function') onseed(existingTorrent)} else {torrent._onTorrentId(torrentBuf)}})})})return torrent}
  • 代码中的关键一句是:
const torrent = this.add(null, opts, onTorrent)
  • 函数最终返回生成的 torrent 对象,其由add函数创建(第一个参数为null),代表正在进行 seeding 的种子。
  • 这句代码实际上启动了种子(torrent)的创建和处理过程。它调用了 this.add() 方法,将 optsonTorrent 回调传递进去,这些回调负责在种子完成处理时执行进一步的操作。
  • 另一个关键的一句是
createTorrent(input, opts, async (err, torrentBuf) => {……})
  • 调用 createTorrent 生成种子文件,并通过 onTorrent 处理后续操作(如 DHT 发布广播等)

  • DHT 广播的过程发生在 onTorrent 回调中的这段代码部分:

if (this.dht) {// DHT 是否启用tasks.push(cb => { // 将一个任务推送到任务队列tasks 中torrent.once('dhtAnnounce', cb) // 监听torrent对象的dhtAnnounce事件。once意味着该事件处理器仅会触发一次,当dhtAnnounce事件发生时,执行回调 `cb`。})
}
  • 当种子(torrent)开始上传并与其他节点建立连接时,WebTorrent 会尝试将种子信息通过 DHT 广播出去,允许其他客户端在没有 Tracker 的情况下发现这个种子。
  • torrent.once('dhtAnnounce', cb) 监听的是这个广播完成后的通知,当种子成功通过 DHT 被宣布时,cb 被执行,表示广播成功。
parallel(tasks, err => {if (this.destroyed) returnif (err) return torrent._destroy(err)_onseed(torrent)
})
  • parallel(tasks, cb) 用来并行执行所有任务,确保所有操作(如文件加载、DHT 广播等)都执行完毕后再继续。
  • 如果没有错误发生,_onseed(torrent) 会被调用,表示种子已经开始上传,并且相关事件会被触发。

add函数

/*** Start downloading a new torrent. Aliased as `client.download`.* @param {string|Buffer|Object} torrentId* @param {Object} opts torrent-specific options* @param {function=} ontorrent called when the torrent is ready (has metadata)*/add (torrentId, opts = {}, ontorrent = () => {}) {if (this.destroyed) throw new Error('client is destroyed')if (typeof opts === 'function') [opts, ontorrent] = [{}, opts]const onInfoHash = () => {if (this.destroyed) returnfor (const t of this.torrents) {if (t.infoHash === torrent.infoHash && t !== torrent) {torrent._destroy(new Error(`Cannot add duplicate torrent ${torrent.infoHash}`))ontorrent(t)return}}}const onReady = () => {if (this.destroyed) returnontorrent(torrent)this.emit('torrent', torrent)}function onClose () {torrent.removeListener('_infoHash', onInfoHash)torrent.removeListener('ready', onReady)torrent.removeListener('close', onClose)}this._debug('add')opts = opts ? Object.assign({}, opts) : {}const torrent = new Torrent(torrentId, this, opts)  // Create a new Torrent instance using the provided torrentId, current client (`this`), and options (`opts`).this.torrents.push(torrent) //Add the new torrent to the list of active torrents.torrent.once('_infoHash', onInfoHash)  //监听 _infoHash 事件来检查是否存在重复的种子。torrent.once('ready', onReady)  // 监听 ready 事件,当种子准备好时执行回调。torrent.once('close', onClose)  // 监听 close 事件,清理资源和事件监听器。this.emit('add', torrent)return torrent}
  • 关键一句是:
const torrent = new Torrent(torrentId, this, opts)
  • 这行代码负责创建一个新的 Torrent 实例,并将其添加到当前 WebTorrent 客户端中,开始处理指定的种子。Torrent类定义在 lib\torrent.js中。相关接口与功能可见docs\api.md的Torrent部分
  • 以下是对 torrent 方法的简单总结,使用表格呈现:
方法名功能描述参数返回值
torrent.destroy([opts], [callback])删除种子,销毁与对等体的所有连接,并删除所有保存的文件元数据。
可以选择销毁存储的文件。
当完全销毁后调用 callback
opts (可选): 配置销毁选项,例如是否销毁存储。
callback (可选): 完成销毁后的回调。
torrent.addPeer(peer)向种子加入一个对等体。通常不需要手动调用,WebTorrent 会自动发现对等体。
手动添加时需确保 infoHash 事件已触发。
peer: 对等体地址(如 “12.34.56.78:4444”)或 simple-peer 实例(WebRTC对等体)。true(添加成功)或 false(被阻止,可能因黑名单)。
torrent.addWebSeed(urlOrConn)向种子加入一个 Web Seed。
Web Seed 是通过 HTTP(S) 提供种子数据的源。
支持 URL 或自定义连接对象。
urlOrConn: Web Seed URL 或自定义连接对象(实现 BitTorrent 协议的 Duplex 流,必须具有 connId)。
torrent.removePeer(peer)从种子中移除一个对等体。WebTorrent 会自动移除慢速或没有所需数据的对等体。
手动移除时指定对等体标识。
peer: 对等体地址(如 “ip:port”)、peer id(hex 字符串)或 simple-peer 实例。
torrent.select(start, end, [priority], [notify])选择一范围的数据块,优先下载该范围内的数据。
可以指定优先级和回调。
start, end: 数据块范围(包含)。
priority (可选): 优先级。
notify (可选): 更新时触发的回调。
torrent.deselect(start, end)取消选择一范围的数据块,从而降低优先级。start, end: 数据块范围(包含)。
torrent.critical(start, end)将一范围的数据块标记为关键优先级,要求尽快下载。start, end: 数据块范围(包含)。
torrent.pause()暂停连接新的对等体。
此操作不影响现有连接或流。
torrent.resume()恢复与新对等体的连接。恢复连接新的对等体,开始与更多对等体交换数据。
torrent.rescanFiles([callback])扫描文件并验证存储中的每个数据块的哈希值,更新已下载的有效数据块的位图。通常用于外部进程添加文件时,确保 WebTorrent 识别这些文件。
完成后会调用回调。
callback (可选): 扫描完成时的回调函数,callback(err)
torrent.on('infoHash', function () {})当种子的 infoHash 确定时触发该事件。
torrent.on('metadata', function () {})当种子的元数据(包括 .torrent 文件的内容)确定时触发该事件。
torrent.on('ready', function () {})当种子准备好使用时触发该事件,表示元数据已就绪且存储准备好。
torrent.on('warning', function (err) {})当种子遇到警告时触发该事件。此事件仅用于调试,不一定需要监听。err: 警告信息。
torrent.on('error', function (err) {})当种子遇到致命错误时触发该事件,种子会被自动销毁并从客户端移除。err: 错误信息。
torrent.on('done', function () {})当所有种子文件下载完成时触发该事件。当所有文件下载完毕时触发,通常用于通知用户下载完成。
torrent.on('download', function (bytes) {})当数据被下载时触发该事件,用于报告当前种子的下载进度。bytes: 本次下载的字节数。用于监控下载进度,返回已下载的字节数,并可查询总下载量、下载速度等。
torrent.on('upload', function (bytes) {})当数据被上传时触发该事件,用于报告当前种子的上传进度。bytes: 本次上传的字节数。用于监控上传进度,返回已上传的字节数。
torrent.on('wire', function (wire) {})每当一个新的对等体连接时触发该事件,wire 是一个 bittorrent-protocol 实现的 Duplex 流。可以使用它来扩展 BitTorrent 协议或进行其他自定义操作。wire: 与对等体连接的流对象。用于处理与对等体的通信,可扩展 BitTorrent 协议或处理自定义协议。
torrent.on('noPeers', function (announceType) {})每隔几秒当没有找到对等体时触发。announceType 指明了导致该事件触发的公告类型,可能是 'tracker''dht''lsd''ut_pex'。如果尝试通过多个方式发现对等体,如跟踪器、DHT、LSD 或 PEX,将会为每种公告分别触发此事件。announceType: 字符串,指示公告类型,可以是 'tracker''dht''lsd'、或 'ut_pex'当没有对等体可用且公告方式不同(例如 tracker、DHT、LSD 或 PEX)时触发此事件。
torrent.on('verified', function (index) {})每当一个数据块被验证时触发。事件的参数是被验证数据块的索引。index: 整数,表示被验证的块的索引。每次数据块的哈希值被验证时触发此事件。

torrent & wire

  • torrent.on(‘wire’, function (wire) {}) 是在 WebTorrent 客户端中,当一个新的对等体(peer)连接时,触发的事件。当这个事件被触发时,wire 会作为参数传递给回调函数。wire 是一个 bittorrent-protocol 的实例,这是一个用于实现 BitTorrent 协议的 duplex 流(双向流),允许客户端与远程对等体(peer)进行数据交换。

  • 以下是一个示例:

import MyExtension from './my-extension'torrent1.on('wire', (wire, addr) => {console.log('connected to peer with address ' + addr)wire.use(MyExtension)
})
  • 实际上torrent中管理者相关的链接对象,如以下代码所示:
client.add(opts.magnetURI,torrent => {const wire = torrent.wires[0];wire.use(MyExtension());wire.MyExtension.on('hack_message', func);})client.seed(buf, torrent => {torrent.on('wire', (wire, addr) => {wire.use(MyExtension());wire.MyExtension.on('hack_message', func);}
})
  • wires 是一个数组,包含与该种子相关的所有 wire 对象。每个 wire 代表与一个对等体(peer)之间的连接。torrent.wires[0] 代表与第一个对等体(peer)建立的连接(wire)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/59464.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【07】Maven项目多环境打包配置

&#xff08;1&#xff09;Web项目使用Maven进行多模块划分开发之后&#xff0c;面临一个问题&#xff0c;即如何加载不同环境的配置文件打包发布到不同的环境中&#xff1f; &#xff08;2&#xff09;不同的环境有开发环境、测试环境、线上生产环境等。 &#xff08;3&#x…

机器学习—前向传播的一般实现

可以写一个函数来实现一个密集的层&#xff0c;那是神经网络的单层&#xff0c;所以定义稠密函数&#xff0c;它将上一层的激活作为输入以及给定层神经元的参数w和b。看下边图片所展示的例子&#xff0c;把所有这些权重向量堆叠成一个矩阵&#xff0c;wnp.array([[1,-3,5][2,4,…

濮良贵《机械设计》第十版课后习题答案全解PDF电子版

《机械设计》(第十版)是“十二五”普通高等教育本科国家级规划教材&#xff0c; 是在《机械设计》(第九版)的基础上修订而成的。本次修订主要做了以下几项工作&#xff1a; 1. 内容的适当更新——自本书第九版出版以来&#xff0c; 机械工程及相关领域的新理论、新技术和新标准…

1分钟解决Excel打开CSV文件出现乱码问题

一、编码问题 1、不同编码格式 CSV 文件有多种编码格式&#xff0c;如 UTF - 8、UTF - 16、ANSI 等。如果 CSV 文件是 UTF - 8 编码&#xff0c;而 Excel 默认使用的是 ANSI 编码打开&#xff0c;就可能出现乱码。例如&#xff0c;许多从网络应用程序或非 Windows 系统生成的 …

曹操出行借助 ApsaraMQ for Kafka Serverless 提升效率,成本节省超 20%

本文整理于 2024 年云栖大会主题演讲《云消息队列 ApsaraMQ Serverless 演进》&#xff0c;杭州优行科技有限公司消息中间件负责人王智洋分享 ApsaraMQ for Kafka Serverless 助力曹操出行实现成本优化和效率提升的实践经验。 曹操出行&#xff1a;科技驱动共享出行未来 曹操…

解析 MySQL 数据库容量统计、存储限制与优化技巧

管理 MySQL 数据库时&#xff0c;了解数据库中的数据量和存储占用情况是非常重要的&#xff0c;尤其是在面对大规模数据时。无论是为了优化数据库性能&#xff0c;还是为了进行容量规划&#xff0c;准确地统计数据库的容量可以帮助我们做出更好的决策。mysql的客户端工具是Navi…

【研究生必备】如何利用AI论文生成器免费提升效率?

在研究生阶段&#xff0c;写论文往往是学业中最具挑战性的部分之一。 面对繁重的文献阅读、复杂的分析和紧迫的时间限制&#xff0c;很多同学都感到压力倍增。不过&#xff0c;随着科技的发展&#xff0c;AI论文生成器的出现为我们提供了一种全新的解决方案。今天&#xff0c;…

Android无限层扩展多级recyclerview列表+实时搜索弹窗

业务逻辑&#xff1a; 点击选择&#xff0c;弹出弹窗&#xff0c;列表数据由后台提供&#xff0c;不限层级&#xff0c;可叠加无限层子级&#xff1b; 点击item展开收起&#xff0c;点击尾部icon单选选中&#xff0c;点击[确定]为最终选中&#xff0c;收起弹窗&#xff1b; 搜索…

位运算的使用与计算机组成的底层计算(java版)

目录 1. 求int类型数字的二进制2. 特殊值展示3. 心得 1. 求int类型数字的二进制 我们可以用位运算的与和左移去求 public class Lesson01 {public static void print(int num){for(int i 31; i >0; i--){System.out.print((num & (1 << i)) 0 ? "0&quo…

写作 | 人工智能在师生教学场景中的应用前景

正文 本文讨论人工智能在师生教学场景中的应用前景。在开展论述前&#xff0c;首先需要明确一些概念。 第一&#xff0c;什么是人工智能&#xff1f;人工智能&#xff08;Artificial Intelligence&#xff09;&#xff0c; 字面意义&#xff0c;即人工制作的智慧能力。这种智慧…

Java线程6种生命周期及转换

多线程技术是我们后端工程师在面试的时候必问的一个知识点&#xff0c;今天就来盘点一下多线程的相关知识&#xff0c; 先来说下进程&#xff0c;线程及线程的生命周期&#xff1a; 进程&#xff1a;进程就是正在进行中的程序&#xff0c;是没有生命的实体&#xff0c;只有在运…

美格智能5G车规级通信模组: 5G+C-V2X连接汽车通信未来十年

自2019年5G牌照发放开始&#xff0c;经过五年发展&#xff0c;我国5G在基础设施建设、用户规模、创新应用等方面均取得了显著成绩&#xff0c;5G网络建设也即将从基础的大范围覆盖向各产业融合的全场景应用转变。工业和信息化部数据显示&#xff0c;5G行业应用已融入76个国民经…

GooglePlay: 应用和游戏的内容分级

对于后台私信的开发者们,希望能够携带详细过审记录和拒审邮件一同发来,方便我们尽快解决问题 应用与游戏 为您的应用或游戏选择类别和标签选择要添加的标签选择类别并添加标签类别示例与应用、游戏以及两者中所投放广告的内容分级相关的要求应用如何获得内容分级内容分级的用…

人工智能学习--ANN模型、SVR模型

人工神经网络 (ANN) 概念 人工神经网络&#xff08;ANN&#xff09;是一种模拟人脑神经元连接结构的计算模型&#xff0c;通过多层神经元和加权连接来处理数据。典型的ANN由输入层、隐藏层和输出层组成。 工作原理 ANN通过传递输入数据至隐藏层神经元&#xff0c;将各层输出…

多线程--模拟实现定时器--Java

一、定时器的概念 定时器的本质就是一个闹钟&#xff0c;时间到了开始执行某些逻辑。Java标准库中的定时器是Timer。 我们查阅Java文档可以详细看到定时器的使用方法&#xff1a; Timer最核心的方法就是schedule方法。值得注意的是我们通常描述任务是使用Runnable来描述&…

FrankenPHP实践

目录 1. 说明 2. 程序修改 3. 性能测试 4. 配置 4.1 Docker化部署 4.2 泛域名和证书设置 4.3 相关命令 5. 要点&#xff1a; 6. 参考 1. 说明 Frankenphp是一个先进的&#xff0c;结合了高性能Caddy服务器的PHP环境框架&#xff0c;它允许用户只需要少量改动&#xff…

2024第三次随堂测验参考答案

7-1 求一组数组中的平均数 输入10个整数&#xff0c;输出这10个整数的的平均数&#xff0c;要求输出的平均数保留2位小数 输入样例&#xff1a; 1 2 3 4 5 6 7 8 9 10 输出样例&#xff1a; 5.50 参考答案&#xff1a; #include <stdio.h> int main(){int sum 0;…

Docker 镜像体积优化实践:从基础镜像重建到层压缩的全流程指南

​ 由于最近在发布的时候发现docker镜像体积变得越来越大&#xff0c;导致整个打包发布流程变得非常耗时了。所以又接到一个差事&#xff0c;优化最终镜像体积。顺便也记录一下docker镜像体积优化的一些步骤。 大概步骤可以分为以下几个步骤&#xff1a; 重做基础镜像&#x…

[linux 驱动]PWM子系统详解

目录 1 描述 2 结构体 2.1 pwm_chip 2.2 pwm_ops 2.3 pwm_device 2.4 pwm_class 3 相关函数 3.1 注册与注销 PWM 控制器 3.1.1 pwmchip_add 3.1.2 pwmchip_remove 3.2 申请与释放 PWM 设备 3.2.1 pwm_request 3.2.2 devm_pwm_get 3.2.3 pwm_free 3.3 控制 PWM …

Linux入门(2)

林纳斯托瓦兹 Linux之父 1. echo echo是向指定文件打印内容 ehco要打印的内容&#xff0c;不加任何操作就默认打印到显示器文件上。 知识点 在Linux下&#xff0c;一切皆文件。 打印到显示器&#xff0c;显示器也是文件。 2.重定向 >重定向操作&#xff0c;>指向的…