跳转到内容

点对点 (P2P) 网络与协议 / Gnutella

来自 Wikibooks,开放世界中的开放书籍

Gnutella 是一种开放的文件共享网络,最初由 Nullsoft 的 Justin Frankel 创建。这意味着,与大多数其他网络不同,任何人都可以编写一个客户端来访问 GNet,只要它符合公开可用的规范。

规范由GDF(Gnutella 开发论坛)进行讨论和创建,这是一个开放的开发者邮件列表,目前拥有超过 1000 名成员。然后,这些规范将在rfc-gnutella中进行文档化。通过这种方式,所有程序都共享一个共同的基础,同时该协议也允许客户端特定的选项。开发人员小心地确保最大程度的向后兼容性。


Clipboard

待办事项
[http://rfc-gnutella.sourceforge.net/developer/testing/index.html RFC-Gnutella 0.6]


尽管有这个名字,Gnutella 并不是 GNU 软件,尽管一些 Gnutella 客户端是 GPL 许可的。它是一个开放的网络,其名称的起源更容易通过吃太多 Nutella 找到,而不是在 GNU 中找到。(这意味着:Gnutella 不是 FSF 的项目,也不与 GNU 软件工具相关)。虽然 Gnutella 最初被声明为一种完全分布式信息共享技术,但该协议的后续版本是集中式和分布式网络的混合,包括“服务器”(超级节点或超级对等方)和“客户端”(叶子节点或节点)。

Gnutella 客户端软件本质上是一个微型搜索引擎(提供对网络搜索引擎的替代)和文件服务系统一体。Gnutella 在新的实现中还支持 Tiger 树散列 (TTH) 用于文件传输。

Gnutella 的一个兄弟值得特别关注,尽管当前客户端的一些开发人员会否认这一点。它被称为 MP(Mike 的协议)或大多数 Gnutella 开发人员所说的 Shareaza 协议,而它的开发人员称之为 Gnutella2,这个名字让他的程序(Shareaza)获得了大量媒体报道,并在_gdf中引发了许多争议和反感。

Gnutella2 (Mike 的协议,G2)

由于开发者社区未能就协议演进达成共识,导致了 Gnutella 协议的分支

Gnutella2 也被称为 Mike 的协议,因为第一个更改和实现来自单个开发人员Michael Stokes。2002 年 11 月,Michael Stokes正式且单方面宣布创建 Gnutella2 协议,提交给Gnutella 开发者论坛,这在开发者之间引起了分歧,并导致修改不被几个 Gnutella 应用程序支持,因为最初的提议与其他供应商的概念冲突(特别是 LimeWire 和 Bearshare)。

现在生成的实现放弃了所有旧的 Gnutella 协议,除了连接握手,并采用了一种全新的搜索算法。Gnutella2 通常缩写为G2


Clipboard

待办事项
完整信息


网络模型

[编辑 | 编辑源代码]

最初的:FoF

[编辑 | 编辑源代码]

你可以将 Gnutella 网络的最初模型想象成朋友打电话相互获取信息。一个人问另外 5 个人,每个人又问另外 5 个人,以此类推。在第一步之后,到达的人数是 5,第二步是 25,第五步是 3125,第七步是 78,125,第 14 步大约是 61 亿。这足以覆盖地球上的每个人。最初的 Gnutella 使用了 7 步(称为 HTL:跳跃到生存)。

这个模型最大的问题(除其他外)是,你必须成为该圈子的一部分才能使用它。

FoF 模型的问题
[编辑 | 编辑源代码]

朋友的朋友模型有一些缺点,这些缺点源于搜索执行的方式。如果搜索结果过多,连接你的节点(你最近的 5 个朋友)可能会过载,因为每个答案都必须经过他们,因为他们不会给出你的“电话号码”,而是给出他们自己的号码,然后将答案传递给你。如果你问大学校长的名字,实际上你会得到数百个答案,而在网上你会得到数千甚至数百万个答案。此外,如果每个问题都被传递给一个拥有 75,000 到 600,000 台计算机的网络中的每个人,并且每台计算机每小时只询问一次,那么他们中的每一个人都必须每秒回答大约 130 到 1600 个问题。而且他们必须将这些问题传递下去。虽然计算机速度很快,并且如今的互联网连接与几年前相比可以处理大量信息,但这对于它们来说还是太多了。想象一下,你的电话整天不停地响,全是各种各样的问题。

为了解决连接问题,人们提出了一些解决方法。

第一种方式:Pong 缓存
[编辑 | 编辑源代码]

Pong 缓存意味着节点(即你)询问它的朋友他们是谁的朋友。这意味着你的朋友将你介绍给他们的朋友,尤其是他们高度重视的朋友,你将所有新地址都写入你的电话簿,这样你就可以知道在你的原始朋友休假时该给谁打电话(有点像在不断的鸡尾酒会上)。这很简单,并且具有为你提供非常可靠的联系人的优势,但如果没有至少认识一个已经在网络中的联系人,你就无法加入网络。这意味着你总能重新加入,但如果你从未加入过,你就无法连接。

第二种方式:记住谁回答
[编辑 | 编辑源代码]

第二种方式非常简单。当你其中一个朋友回电说 Smith(你以前不认识他)知道一些事情时,你会记下她的号码。当你下次将他作为你的五个直接联系人之一打电话时,更有可能你能够更快地获得信息,因为他可能有与你兴趣相似的朋友(他应该从哪里获得信息?),并且那些朋友比随机挑选的人更有可能拥有你的信息(至少当你询问与你上次问题类似的事情时)。缺点是这些联系人可能不会经常在家,所以你可能会发现一个知识渊博的联系人,但你可能再也无法联系到他了。仍然没有办法在第一次尝试时加入网络。现在我们来看看 Gnutella 中的最新发展之一:GWebCaches。我将在下一部分中讨论它们。

第三种方式:GWebCaches
[编辑 | 编辑源代码]

为了保持图像一致性,GWebCache 就像一个在报纸上发布电话号码并记录来电者的联系人。当你离开一段时间后,不再确定你的联系人是否还使用同一个手机号码,你就可以致电这个公开的联系人。在提供号码之前,他们会问你:“你认识其他公开的联系人吗?如果认识,请告诉我他们的号码。” 这样做是因为他们无法阅读所有报纸,而你却可以随时阅读,而且不需要为此付出太多努力。这样,他们就能互相联系。然后,该联系人会提供一些电话号码给你,并记下你的号码(以便提供给其他人)以及他们认识的其他公开联系人(GWebCaches)的地址。

这就是 GWebCaches 工作原理的大致过程。GwebCaches 只对第一次连接至关重要。当你本地地址簿为空时,你会用到它们。你不应该优先使用它们,而应该优先使用本地地址簿。正如我所说,它们是 Gnutella 中的新发展之一,因此我将继续介绍 Gnutella 中的一些最新变化和未来计划。

超级节点和叶子节点

[edit | edit source]
改变谁呼叫谁

你肯定有朋友认识很多其他人,你可以向他们询问,并且可以肯定他们会知道确切的可以给你答案的人。在 Gnutella 中,这些被称为超级节点。超级节点不需要自己知道太多,他们只需要知道谁知道就行了。在 Gnutella 中,这意味着一个好的超级节点不需要拥有很多文件就能对网络有所帮助。如果你害怕分享太多内容,你应该在 Gnutella 中成为一个超级节点。

更详细的解释

在计算机世界中,就像在现实世界中一样,有些联系人可以处理更多电话,有些联系人无法经常打电话(或者负担不起电话费)。在现实世界中,这是因为他们有更多空闲时间。而在计算机世界中,这是因为他们拥有更快的连接(如 DSL、Cable、T1、T3 或类似的宽带)。在意识到这一点后,开发人员决定改变网络拓扑结构,也就是说当你绘制网络时它从外部看起来的样子。现在你不再只是呼叫任何朋友,而只呼叫那些你知道有时间接听你的电话并将电话转接到其他人的人。为了避免你接到太多电话,他们会询问你拥有哪些类型的信息,或者用更人性化的话来说,你的专业领域是什么。在计算机世界中,这意味着你的计算机会将所有文件的列表发送给超级节点,这就是我们对这类联系人的称呼。该列表包含你共享的所有文件的摘要(哈希字符串)(你决定让其他人下载的那些文件),下载者可以通过这些摘要验证它们是否是他们想要的那些文件。每当电话到达超级节点时,它会检查你是否可能知道答案,只有在这种情况下才会呼叫你。

这些超级节点与其他节点有许多连接,这意味着他们拥有一个非常大的地址簿。通常情况下,他们会与地址簿中的 16 个其他超级节点保持联系,并将问题发送给他们,这些超级节点又会将其发送给另外 16 个超级节点,以此类推。他们还拥有大约 16 个叶子节点,这些叶子节点无法或不愿意经常打电话,他们会从这些叶子节点接收电话,并且知道他们的文件或,对人类世界来说,他们的专业领域。

这看起来似乎对超级节点来说很不公平,因为他们为了保持网络完整性而投入的资源远远超过叶子节点,但事实并非如此。虽然超级节点(UP)花费了大量时间来维护网络运行,但叶子节点专门收集和传递信息。因此,当任何节点,无论是超级节点还是叶子节点,想要了解某个信息时,他们只需发起一个电话,就可以由一个叶子节点专家向他们解释。这样一来,人们就可以专注于自己的专业领域,让所有人都能从中受益。

超级节点内查询路由协议
[edit | edit source]

虽然有了超级节点,并非每个人都需要参与向他人发送问题,人们可以专注于分享他们的信息,但超级节点仍然会将每个问题发送给所有人,而不会考虑该超级节点是否有拥有这些文件的叶子节点。这听起来很正常,因为超级节点如何才能知道其他超级节点拥有哪些文件呢?答案再次来自现实生活。普通人知道自己的朋友,也知道他们中哪些人可能知道某个特定问题的答案,哪些人肯定不知道。在现实生活中,这主要通过友好的聊天来完成。

现在,计算机通常不会闲聊,因此它们不会通过这种方式交换信息。因此,查询路由协议(QRP)应运而生。在 QRP 中,每个叶子节点都会告诉其超级节点它拥有哪些文件,但它们不会使用文件名,因为这会占用太多空间,而是将构成文件名中每个词语的字母保存为数字(毕竟这是计算机)。你可以将这个过程想象成一个战舰游戏(数字形成一个带有两个坐标的棋盘)。一个超级节点不会将所有问题发送给叶子节点,而只会发送那些叶子节点可能能够回答的问题(命中一艘战舰),因此叶子节点接收到的不必要电话会少很多。

现在,既然这可以减轻叶子节点的压力,为什么不将其扩展呢?事实确实如此。现在,所有超级节点都将他们的棋盘发送给直接邻居。他们只会将那些还需要一步才能找到答案的搜索发送给棋盘上得分命中其他超级节点。这意味着,搜索的最后两步只有在有可能得到结果时才会进行。你可以很容易地理解为什么这会大大减少带宽使用率:想象一棵树,一棵普通的树,而不是那些数学结构中的树。如果你试图数叶子,你几乎没有机会。但是,如果你去掉叶子,只数树枝,你的工作量就会少很多。如果你现在去掉所有那些细小的树枝,你就可以真正开始数它们了。QRP 并没有去掉所有的叶子和所有细小的树枝,而是去掉了那些无法给你答案的叶子和细小的树枝。由于每个问题必须经过的部分都会消耗带宽,而叶子比树枝多得多,在很多情况下,去掉最后两步中的很多步(也就是说很多叶子和细小的树枝),就可以减少计算机需要发送的问题数量(叶子比树枝多得多)。这个例子并不适用于整个 Gnutella,但在这里它很贴切。

搜索:动态查询
[edit | edit source]

现在,虽然超级节点模型和 QRP 部分解决了以下问题:你没有时间向其他人解释清楚某件事,或者让其他人解释清楚,因为电话不断响起,询问你不知道答案的问题(或者用技术术语来说:因为网络流量超过了你的连接速度),但仍然存在另一个问题,如果你仔细观察,通常可能不会被注意到。在现实世界中,超级节点会寻找一个专家,直到找到一个可以给你提供信息的人,然后就会停止。在计算机世界中,问题会被不断发送,发送给尽可能多的联系人,而不考虑是否已经有了答案。

有了动态查询,这种情况就发生了改变。现在,超级节点一次询问一个其他超级节点,然后等待一段时间,看看是否得到了答案。当他们获得足够多的答案以满足他们的要求时,他们就会停止询问。这听起来很自然,但对 Gnutella 来说是一个巨大的进步,因为它节省了浪费在非常流行的问题上的资源。我再以大学领导为例:现在,如果你询问大学领导,你的超级节点会首先查看他们是否直接认识可以回答你问题的人。然后,他们只会给你一些他们认识住在校园里的人的号码。你仍然会得到不止一个答案,因为他们会给你不止一个号码,因为他们无法确定你是否能联系到他们给你的每个号码。但是你不会收到数千个电话号码(来自校园里的每个学生),首先是因为超级节点会浪费时间去做一些对你没有额外帮助的事情,其次,因为你不可能永远联系所有那些人,第三,因为这样你可能再也联系不上你的超级节点,因为他们会忙着回复其他告诉他们号码的人的电话,并将你的问题发送给其他超级节点。

在没有搜索的情况下查找来源,即下载网格

[edit | edit source]

现在你可能会说,“但我无法从这三个人那里下载,因为其他人已经在下载了。我想获取所有可以从那里下载的地址。”(而且你不是唯一有这种想法的人。我也这么认为。)通过观察现实世界,我们可以找到解决这个问题的方法,而不必浪费太多资源。在现实世界中,如果你要求专家向你解释某件事,而该专家很忙,他们会知道一些其他可能现在有更多时间的专家(因为他们相互认识)。

将这应用于 Gnutella 并不像超级节点-叶子节点模型或动态查询模型那么容易。但程序员找到了一种方法。正如我在动态查询模型中所述,你将获得多个可以询问的号码。现在,当你呼叫一个应该知道答案的人时,你还会告诉他或她你所知道的其他号码。这样,这些专家就会相互认识(就像我之前提到的 GWebCaches 那样,他们互相了解)。由于每个人在询问时都会带上自己的一组号码,因此专家们会了解越来越多的其他地址,当你要求他们解释,而他们现在没有时间时,他们会将这些地址给你(即使他们有时间,他们也会这样做,以防他们被打断,因为在 Gnutella 中,你可以从多个来源同时下载,就像你在 overnet 网络中一样(overnet 网络对此做到了极致,但只对大型文件真正高效)。此外,专家们也会将你添加到他们的备用联系人列表中,只要你了解足够多的知识可以教导他人。

这就是为什么很多人会从你那里下载你刚刚自己下载的文件的原因。

下载

[edit | edit source]
群组下载和部分文件共享
[编辑 | 编辑源代码]

蜂群的概念很容易解释(但在朋友的朋友模式下很难实现,所以我只在这一部分中放弃它)。它的工作原理很简单,就是同时从不止一个人那里获取一个文件。文件被简单地分成几个部分,就像你想要从一些朋友那里得到一本书,每个人只复印了几页。当要求每个人复印书的不同部分时,你就可以得到完整的书,而每个人只需要做很少的工作(如果一个人没有时间做,其他人可以做)。

蜂群在下载网格和部分文件共享 (PFS) 中效果最好,这允许人们共享他们正在下载的文件,因为他们可以共享他们已经拥有的部分,而他们仍然从其他人那里下载。你可以复印你拥有的那些页面,而不需要拥有整本书,因为你的页面都有编号,朋友可以向你索取特定的页码。

通过防火墙下载
[编辑 | 编辑源代码]

想象一下,有些人无法被呼叫,但只能呼叫其他人(也许是因为他们只使用公共电话,或者他们的号码没有显示在你的手机上,他们不喜欢公布号码,因为他们不喜欢被推销电话骚扰,或者被电话恐吓的人骚扰)。在 Gnutella 中,这些是在防火墙后面的计算机。他们可以呼叫其他人并从他们那里获取信息,但没有人可以呼叫他们。

解决方案是让防火墙后面的人定期呼叫他们的超级节点,当有人想要呼叫他们时,他或她只需要呼叫超级节点,然后超级节点将两个电话放在一起,一个电话是防火墙后面的人(不能被呼叫的人)接通的,另一个电话是你呼叫的。这样你就可以和防火墙后面的人通话,但需要同时进行两次呼叫,这意味着在计算机世界中需要两倍的带宽。防火墙后面的人总是保持与超级节点的连接,超级节点只是中继信息或数据。

有一些计划可以节省超级节点的额外带宽使用,方法是让其他人来进行电话连接。然后,当有人想从防火墙后面的专家那里获取信息时,超级节点会告诉防火墙后面的人和提问者呼叫第三个人。然后这个人会把两个电话放在一起。在 Gnutella 中,大多数人有 3 到 5 部电话,所以这不是一个大问题。这些电话连接器很可能被称为路由节点。

文件磁力链接

[编辑 | 编辑源代码]

文件磁力链接偏离了朋友的朋友模型。它们是网页上的链接,你可以直接点击,它会告诉你的文件共享程序在 Gnutella(事实上也包括其他网络)中搜索特定文件,并下载该文件。

你可以把它想象成报纸上的一篇文章,它告诉你一些信息,这些信息可以让你了解超级节点所需的信息,以便从你想要学习的专家那里获得信息。在现实世界中,你很可能找到一个专家,以及从他或她那里学到东西的人。

使用磁力链接可以避免获取不良文件,因为它们使用哈希字符串,这就像专家给你的信息的摘要。如果他或她开始告诉你废话,你马上就能看到它与摘要不符。在 Gnutella 中,程序要求文件,这些文件由拥有它们的人分配了相同的摘要,即哈希字符串。下载后,程序会生成自己的摘要,并检查它们是否真的匹配。如果不匹配,它会告诉你文件已损坏。来自相同文件的摘要总是完全相同的,因为它们是通过特定的数学方法完成的,这些方法在给定相同数据(即信息)时总是得到相同的结果。

与磁力链接不同,KaZaA 链接和 eDonkey 链接并不安全,因为它们使用的方法可以被虚假文件欺骗(例如,KaZaA 链接要求一种只检查信息的介绍和第一部分的摘要,而忽略所有其他部分,以便更快地创建摘要。当然,很容易给你提供虚假信息,因为他们只需要在开头说实话,然后他们就可以撒谎或胡说八道)。有关磁力链接的更多信息,请访问:Magnet-UriMagnetLink.org

现在有一个新的磁力链接版本:KaZaA 磁力链接。遗憾的是,这些并不安全,因为它们使用 KaZaA 哈希系统(不完整的摘要)进行了一些更改(它们现在添加了另一个更小的摘要,它可能告诉你关于缺失部分的信息,但它们没有公布是如何创建的)。如果 KaZaA 磁力链接提供有关搜索词的信息,它们可能与 Gnutella 配合使用,但不能保证你得到它们提供给你的东西。如果在链接中找到“kzhash”这个词,它可能不安全(除了名称有点错误)。

Lime Wire LLC

[编辑 | 编辑源代码]

LimeWire 是一个跨平台的 Java 平台点对点文件共享 客户端,开源(GPL),它使用 Gnutella 网络来定位和传输文件。它还鼓励用户支付费用,然后用户就可以使用 LimeWire Pro。它还使用 C++、Boost 许可的 libtorrent 库支持 BitTorrent 协议。

软件实现

[编辑 | 编辑源代码]

要成为 Gnutella 网络的一部分,你可以使用以下列出的客户端之一 

  • Deepnet Explorerhttp://www.deepnetexplorer.com/)是一个带有 RSS 新闻阅读器、P2P 客户端集成(Gnutella)和钓鱼警报的浏览器,闭源,仅限 Windows,免费软件。
  • Phex 是一个跨平台的 Java 客户端。
  • XoloX
  • Gnucleus - Gnutella、Gnutella2 (G2) 使用 C++ 和 Microsoft MFC 库编写。核心是 LGPL,使用 Windows COM-base 与 GPL 前端通信。
  • Gtk-Gnutella,GPL,用于 GNU/Linux。
  • Hydranode(多协议,在 eDonkey2000/eMule 部分中引用)
  • ezpeer,一个中国客户端。
  • pp365,一个中国客户端。
  • POCO,一个中国客户端,使用 GnucDNA。
  • Bearshare,适用于 Windows 的免费闭源软件。
  • CocoGnut,适用于 RISC OS。
  • Swapper,适用于 Windows 的免费闭源软件,使用 .NET。
  • TrustyFiles,适用于 Windows,支持 FatTrack (KaZaA)、Gnutella 和 G2。
  • Shareazahttp://shareaza.sourceforge.net/),开源(GPL),用 C++、MFC 和 ATL 编写。支持 Gnutella2 (G2)、Gnutella、eDonkey2000/eMule、BitTorrent、FTP 和 HTTP 协议的多网络点对点文件共享客户端。
  • FrostWirehttp://sourceforge.net/projects/frostwire/),是 Gnutella 网络的点对点 (P2P) 信息共享客户端。该项目与 LimeWire LLC 无关。它是 Limewire Java 实现的一个分支,承诺永远不会包含内容过滤器。FrostWires 的源代码 (Java) 在 GNU GPL 开源许可下获得许可。较新的版本已迁移到使用 BitTorrent 协议。
    • Acquisition,一个基于 Limewire 核心、用 Cocoa 编写的 Mac OS X 客户端,共享软件。
    • XNap,一个使用 Limewire Core for Gnutella 的多网络 Java 程序。
华夏公益教科书