当前位置:首页 > 生活百科

torrent是什么格式的文件(torrentkitty磁力搜索引擎使用)

栏目:生活百科日期:2024-12-29浏览:0

阅读目录

Torrent简介Torrent结构Torrent文件编码Torrent文件解析Torrent文件与Magnet具体实现Reference


回到顶部

Torrent简介

BitTorrent协议的种子文件(英语:Torrent file)可以保存一组文件的元数据。这种格式的文件被BitTorrent协议所定义。扩展名一般为“.torrent”。

.torrent种子文件本质上是文本文件,包含Tracker信息和文件信息两部分。Tracker信息主要是BT下载中需要用到的Tracker服务器的地址和针对Tracker服务器的设置,文件信息是根据对目标文件的计算生成的,计算结果根据BitTorrent协议内的Bencode规则进行编码。它的主要原理是需要把提供下载的文件虚拟分成大小相等的块,块大小必须为2k的整数次方(由于是虚拟分块,硬盘上并不产生各个块文件),并把每个块的索引信息和Hash验证码写入种子文件中;所以,种子文件就是被下载文件的“索引”。

回到顶部

Torrent结构

Torrent文件内容都以Bencoding编码类型进行存储,整体上是一个字典结构,见下:

Torrent总体结构

键名称数据类型可选项键值含义
announcestringrequiredTracker的Urlinfodictionaryrequired该条映射到一个字典,该字典的键将取决于共享的一个或多个文件announce-listarray[]optional备用Tracker的Url,以列表形式存在commentstringoptional备注created bystringoptional创建人或创建程序的信息

Torrent单文件Info结构

Torrent多文件Info结构

files字典结构:

Torrent实际结构预览

以JSON序列化整个字典后,单文件和多文件的结构大致如下,注意:JSON内容省略了pieces摘要大部分内容,仅展示了开头部分,另外由于本人序列化工具设置所致,所有的整型都会序列化成字符串类型。

单文件结构

多文件结构

{    "creation date": "1604347014",    "comment": "Torrent downloaded from https://YTS.MX",    "announce-list": &[        &[            "udp://tracker.coppersurfer.tk:6969/announce"        ],        &[            "udp://9.rarbg.com:2710/announce"        ],        &[            "udp://p4p.arenabg.com:1337"        ],        &[            "udp://tracker.internetwarriors.net:1337"        ],        &[            "udp://tracker.opentrackr.org:1337/announce"        ]    ],    "created by": "YTS.AG",    "announce": "udp://tracker.coppersurfer.tk:6969/announce",    "info": {        "pieces": "?im??u000b*???... ...",        "name": "Love And Monsters (2020) &[2160p] &[4K] &[WEB] &[5.1] &[YTS.MX]",        "files": &[            {                "path": &[                    "Love.And.Monsters.2020.2160p.4K.WEB.x265.10bit.mkv"                ],                "length": "5215702961"            },            {                "path": &[                    "www.YTS.MX.jpg"                ],                "length": "53226"            }        ],        "piece length": "524288"    }}

回到顶部

Torrent文件编码

根据上文所说,Torrent文件均以Bencoding编码进行存储,故我们需要大致了解一下Bencoding编码。

Bencoding以四种基本类型数据构成:

string : 字符串intergers : 整数类型lists:列表类型dictionary:字典类型

字符串类型

字符串类型由以下结构表示:字符串长度:字符串原文,例如:
42:udp://tracker.pirateparty.gr:6969/announce。

整形类型

整形类型由以下结构表示:i&<整形数据&>e,例如i1234e,则表明的整形数据为1234。

列表类型

列表类型由以下结构表示:l&<列表数据&>e,即列表以字母l开头,以字母e结束,中间的均为列表中的数据,中间的值可以为任意的四种类型之一。

字典类型

字典类型由以下结构表示:d&<字典数据&>e,即字典由字母d开头,以字母e结束,中间的均为字典中的数据,中间的值可以为任意的四种类型之一。

实际组合解析

根据上述描述来看看实际的内容解析,我们以下方的数据为例:

d8:announce49:udp://tracker.leechers-paradise.org:6969/announce13:announce-listll49:udp://tracker.leechers-paradise.org:6969/announceel48:udp://tracker.internetwarriors.net:1337/announceeee

大家可以先尝试根据上面的内容对这一串内容进行解析,我将这一串数据拆分开来方便大家理解和查看,可以明显看出其由一个拥有两个键值的字典,其中一个键为announce,另一个键为announce-list,两者的值一个为
udp://tracker.leechers-paradise.org:6969/announce,一个为列表,列表内还嵌套了一层列表。

d  8:announce    49:udp://tracker.leechers-paradise.org:6969/announce  13:announce-list      l         l           49:udp://tracker.leechers-paradise.org:6969/announce         e         l           48:udp://tracker.internetwarriors.net:1337/announce         e      ee

回到顶部

Torrent文件解析

根据上文对Torrent文件编码的了解,那么我们使用代码对Torrent文件就很简单了。我们只需要读取种子字节流,判断具体是哪种类型并进行相应转换即可。

即:读取文件字节,判断字节属于哪一种类型:0-9 : 字符串类型、i:整形数据、l:列表数据、d:字典数据

再根据每个数据具体类型获取该数据的内容,再读取下一个文件字节获取下一个数据类型即可,根据这个分析,伪代码如下:

获取字符串值

// 当读取到字节对应的内容为0-9时进入该方法String readString(byte&[] info,int offset) {// 读取‘:’以前的数据,即字符串长度int length = readLength(info,offset);// 根据字符串长度,获取实际字符串内容    string data = readData(info,length,offset);    // 返回读取到的字符串内容,整个读取过程中读过的偏移量要累加到offset    return data;}

获取整数类型

这里有一个注意项,考虑到数据边界问题,例如java等语言,推荐使用Long类型,以防数据越界。

// 当读取到的字节对应的内容为i时,进入该方法Long readInt(byte&[] info,int offset) {// 读取第一个'e'之前的数据,包括'e'    string data = readInt(info,offset)    return Long.valueOf(data);}

获取列表类型

因为列表类型中可以夹杂所有四种类型中任意要给即需要用到上面两个方法。

// 当读取到的字节对应的内容为l时,进入该方法List readList(byte&[] info,int offset){    List list = new List();    // 读取到第一个'e'为止    while(info&[offset] != 'e'){        swtich(info&[offset]){            // 如果是列表,读取列表并向列表添加            case 'l':              list.add(readList(info,offset));              break;            // 如果是字典,读取字典并向列表添加            case 'd':              list.add(readDictionary(info,offset));              break;            // 如果是整形数据,读取数据并向列表添加            case 'i':              list.add(readInt(info,offset));              break;            // 如果是字符串,读取字符串数据并向列表添加            case '0-9':              list.add(readString(info,offset));        }    }    // offset向前移一位,把列表的结束符'e'移动为已读    offset++;    return list;}

读取字典类型

读取字典类型与列表十分相似,唯一不同的就是需要区分键值,字典的键值可能为字符串,故依此来判断。

// 当读取到的字节对应的内容为d时,进入该方法Dictionary readDictionary(byte&[] info,int offset){    Dictionary dic = new Dictionary();    // key为null时,字符串为键,否则为值     String key = null;    // 读取到第一个'e'为止    while(info&[offset] != 'e'){        swtich(info&[offset]){            // 如果是列表,读取列表并向字典添加,添加列表时肯定存在键,直接添加并将键置空            case 'l':              dic.put(key,readList(info,offset));              key = null;              break;            // 如果是字典,读取字典并向字典添加,添加字典时肯定存在键,直接添加并将键置空            case 'd':              dic.put(key,readDictionary(info,offset));              key = null;              break;            // 如果是整形数据,读取数据并向字典添加,添加整形数据时肯定存在键,直接添加并将键置空            case 'i':              dic.put(key,readInt(info,offset));              key = null;              break;            // 如果是字符串            case '0-9':              string data = readString(info,offset);              // key为null时,字符串为键,否则为值               if(key == null){                  key = data;              }else{                  dic.put(key,data);                  key = null;              }        }    }    // offset向前移一位,把列表的结束符'e'移动为已读    offset++;    return dic;}

回到顶部

Torrent文件与Magnet

磁力链接与Torrent文件是可以相互转换的,此文只讨论根据Torrent文件如何转换为Magnet磁力链接。

Magnet概述

磁力链接由一组参数组成,参数间的顺序没有讲究,其格式与在HTTP链接末尾的查询字符串相同。最常见的参数是&”xt&”,是&”exact topic&”的缩写,通常是一个特定文件的内容散列函数值形成的URN,例如:

magnet:?xt=urn:bith:YNCKHTQCWBTRNJIV4WNAE52SJUQCZO5C

注意,虽然这个链接指向一个特定文件,但是客户端应用程序仍然必须进行搜索来确定哪里,如果有,能够获取那个文件(即通过DHT进行搜索,这样就实现了Magnet到Torrent的转换,本文不讨论)。

部分字段名见下方表格:

字段名含义magnet协议名xtexact topic的缩写,包含文件哈希值的统一资源名称。BTIH(BitTorrent Info Hash)表示哈希方法名,这里还可以使用ED2K,AICH,SHA1和MD5等。这个值是文件的标识符,是不可缺少的。dndisplay name的缩写,表示向用户显示的文件名。这一项是选填的。trtracker的缩写,表示tracker服务器的地址。这一项也是选填的。bithBitTorrent info hash,种子散列函数

Torrent转换为Magnet

dn : 向用户显示的文件名

即为Torrent文件中,Info字典下的name键所对应的值

tr : tracker服务器地址

即为Torrent文件中,announce以及announce-list两个键所对应的值

bitch : 种子散列值

即为Torrent文件中,info对应的字典的SHA1哈希值(Hex)
根据下图,为4:infod,以d的地址作为哈希原文的起始索引,则为Adress:00 01A3

到整个info结束,以e的地址作为哈希原文的终止索引地址,则为Adress:03 0BE7

根据上述可知:

magnet = 'magnet:?xt=urn:btih:'+Hex(Sha1(info))+'&&dn='+encode(name)+'&&tr='+encode(announce)

结合上一部分的实现,我们可以在读取info时记录startindex和endindex,即:

Dictionary readDictionary(byte&[] info,int offset){//...    case 'd':      bool record = key == 'info';      if(record){          startindex = offset;      }      readDictoinary(info,offset);      if(record){          endindex = offset      }}string getBith(byte&[] info,int start,int end){  // 获取info中从start到end的字节数组,并对其进行摘要计算  byte&[] infoByte = new byte&[infoEnd - infoStart + 1];  System.arraycopy(torrentBytes, infoStart, infoByte, 0, infoEnd - infoStart + 1);  return Hex.toHex(Sha1.toSha1(infoByte));}

回到顶部

具体实现

本人通过Java实现了以上部分逻辑(Torrent文件解析以及Magnet链接生成),若有需要参考的读者可以到以下网址获取相关内容:

工具类目录:
https://github.com/Rekent/common-utils/tree/master/src/main/java/com/rekent/tools/utils/torrent

解析类源码:
https://github.com/Rekent/common-utils/blob/master/src/main/java/com/rekent/tools/utils/torrent/TorrentFileResovler.java

依赖jar包:
https://github.com/Rekent/common-utils/releases/tag/v0.0.3

调用方式:

public void testResolve() throws Exception {String path = "C:\Users\Refkent\Downloads\Test.torrent";TorrentFile torrentFile = TorrentFileUtils.resolve(path);System.out.println(torrentFile.print());System.out.println(torrentFile.getHash());System.out.println(torrentFile.getMagnetUri());}

“torrent是什么格式的文件(torrentkitty磁力搜索引擎使用)” 的相关文章

为什么excel公式不自动计算(excel自动计算方式)

在Excel表格做数据统计时,如果碰到下拉单元格公式不自动计算,这时该怎么办呢?接下来,跟大家介绍下如何解决这个问题。例如下表格是求和计算,但是下拉后结果是一样...

vin号怎么看(中国汽车网vin查询系统)

目录:一、车辆识别代号/车架号/VIN是什么二、VIN有何含义三、VIN有什么用四、VIN如何查看五、VIN是否可以修改六、VIN有打磨痕迹的可以上牌吗1车辆识...

什么是cdn加速,CDN加速服务加速的作用

简单来说,当一个网站开启了CDN加速,其给用户的感觉是访问网站速度或者下载东西的速度会明显比没有开启加速更快,变快或者下载东西变快了。CDN核心目的就是使用户可...

产品经理kpi考核方案(最值借鉴的kpi考核方法)

部门及个人的绩效指标是公司关键业绩指标的分解,也是部门及个人计划的目标及完成情况的评价指标在公司级KPI的基础之上,结合部门职责制定部门/项目公司KPI,该指标...

一键开店对原来的店有影响吗(浅谈其潜在影响)

公司送餐的阿姨感觉是个体户,每天风雨无阻准时送餐,两荤一素16元可以说是物有所值。但阿姨接餐的方式却是最传统的群内接龙,即便用上了最新的群工具,接龙还是经常出现...

2023人均gdp排名城市(GDP城市排名情况)

我国幅员辽阔,人口众多,在经济和城镇化发展的过程中,人口往往会流向经济更发达、各类资源更集中的大城市,从而出现了多个人口规模超千万的特大城市,如果区域间大城市联...

在街上卖什么最赚钱,18种最赚钱的路边摊

引导:地摊经济横空出世,作为新手,你应该卖什么赚钱呢?今天我们就来盘一下摆地摊卖什么好!正文:大家好,我是才情。今年因为疫情的原因,很多行业都不好做,生意惨淡,...

微信h5是什么,简述h5秀和图文的区别

1月26日,微信官方发布《关于近期诱导违规及恶意对抗的处理公告》,通报了近期外链在微信朋友圈违规推广的行为及处理措施。一时间,朋友圈草木皆兵。《测试类H5别做了...

小城市什么生意利润高前景好(5个不起眼适合新手一个人

这段时间,全国的就业市场都不太景气,很多在城市打工的农民朋友也感受到了压力,有的在想要不要干脆自己做门小生意。但对于手头余钱不多的普通家庭,风险问题总是让人担忧...

ipad一代笔怎么充电(ipad历代机型一览)

最近数码盖饭写闲鱼相关的文章比较多,就是自己爱上了闲鱼捡垃圾,每天刷闲鱼的时间比刷抖音的时间还多,看着闲鱼上的数码垃圾,非常的动心,已经买了不少的平板,其中这个...