我是一颗种子。
叮,叮。。。某雷的下载完成提示音,大家应该还不陌生,上学时下课后宿舍内尽是叮叮叮有木有。。。
“叮”有时候是结束的标志, 也可能是隐私娱乐开始的暗示,毕竟下载完成就可以干自己的事了。。。
少年们在我面前,是没有秘密的。。。
在人类的世界里,互联网除了承载电商,交友,还承载了巨量的娱乐内容,隐私的娱乐,我的存在,要感谢互联网,感谢P2P。
那年还在花开的少年们,尽情享受P2P带来的红利。
私娱是一件伟大的事,是一件绽放人性的过程。然而一切的一切,都要始于一个文件,那就是我。
为了找到一个或者一种类型种子,有多少少年曾经通宵去认真研究电驴,P2P Search,某雷的玩法甚至协议。。。
上面这条流程谁没走过站出来秀一波。。。从前往后越来越黄,少年在不归路上越走越远。
种子里有什么
主人创建我的时候,会在考虑什么呢, 标题,介绍,谁主演的?
歇会先,先给大家普及下P2P吧,别搞错,这不是跑路的P2P。
P2P的世界
P2P的世界是如何构成 的
要去下载内容,得知道从哪下载, tracker service承担了这个查询的活。
在P2P世界里,少年们原理上是平等的, 下载了别人的文件,也就自动提供了被下载的能力。如何让别人知道有这个文件,只需要告诉tracker service。
在P2P的世界里,我是一个连接器。
我的个人介绍里有其对应的tracker server地址。
除此之外,还有概要信息
端到端的连接
端到端通过tracker service知道对方后,相互连接并交换信息与文件。
网络情况太危险了,充满了各种危险与欺诈,黑客们可能想把病毒伪装成文件供别人下载,因此
规则设计需要对文件进行校验。
当下载完成时需要对文件的hash值与种子文件中的hash值进行比较,这样如果下载的内容不是想要的,则会校验失败。
随着生活质量的提高, 人们对内容的高清的追求不断提高,如果一个番号有十几个资源,在网速允许的情况下,最高清的会是
终极目标,有时宁愿多花几个小时,这也许就是人性吧。。。
这便有了一个问题,少年花了一天的时间下载了10G的avi, 最后校验失败, 撸管失败。。。
于是校验开始切片化,将一个文件切成一片片的,每256K校验一下,少年从此不用担心下错的问题。
我提供了文件与文件切片的校验值
校验值,每段40个字节
一颗种子的自我解码
既然我知道so 多真相,是不是很牛B,有多少少年第一次接解 牛 B是从我开始, 所以我的自我的编码叫B编码吧, 翻译过去叫bencode.
言归正传,上面的截图可以看到很多的列表,比如文件列表,切片列表,tracker列表,所以B编码中需要包含对列表的处理,
此外还有KV型(key-value) ,俗称字典型。以及整型,字符串。
简单点
整型: i3e 代表3
列表型: l[列表内容]e
KV型: d[KV列表]e
字段: 6:yellow 表示yellow, 长段摆在前面。
比如d4:lovel6:yellow6:beautyee 代表有一个KV, K=love, V是个列表,包含"yellow"与“beauty”。
实现一个牛B解码
代码这个事,有点枯燥,哎哟,这个事怎么说起呢。。。
在编码上,其实我是一个由很多KV组成的字典(dict),[name:..., comment:...], 所以咱们就从解析开始dict开始:
咱们将这个字典打印出来:
整理一下:
着重介绍下对KV的解码:
解析KV的value:func (d Decoder)parseKV(dict BDict, key *string)(bool)
如果是字符串,比如5:hello则调用parseSingleString来解析,如果是list则调用下面的代码解析列表。
再如下面的字符串与整形的解析
解析list的与dict方法类似
func (d Decoder)parseList()(BList, bool)
func (d *Decoder)parseList()(*BList, bool){
d.pos++
d.level++
var ls = &BList{}
for d.pos < d.size {
c := d.data[d.pos]
if c == 'd' {
dc, r := d.parseDict()
if !r {
log.Println("parse dict failed")
return nil, false
}
ls.Eles = append(ls.Eles, dc)
}else if c == 'i' {
i, r := d.parseInt()
if !r {
log.Println("parse dict failed")
return nil, false
}
iv := &BInt{
V : i,
}
ls.Eles = append(ls.Eles, iv)
}else if c == 'l' {
l, r := d.parseList()
if !r {
log.Println("parse list failed")
return nil, false
}
ls.Eles = append(ls.Eles, l)
}else if c >= '0' && c <= '9' {
s, r := d.parseSingleString()
if !r {
log.Println("parse string failed")
return nil, false
}
vs := &BString{
V : s,
}
ls.Eles = append(ls.Eles, vs)
}else if c == 'e' {
d.pos++
break
}
}
d.level--
return ls, true
}
可能会有多重嵌套,比如key:[list], list再包含一个dict等等,因此将各函数定义为func() value的形式会有利于实现。
最终将dict转成我们想要的各式:
func (d BDict) handle() TorrentInfo
P2P的工作流程
不知道有多少人会认真的读到这里,唉少年们这快进快退的习惯可能也曾经与我的文化有关吧,毕竟看片多了自然也就习惯了快进与拖的人生。
我是怎么产生作用
最后,想了解我就请继续关注我吧。