对等名称解析协议
顾名思义,PNRP 旨在基于网格名等要素来解析物理地址。PNRP 可供带有 Advanced Networking Pack 的 Windows XP Service Pack 1 (SP1) 以及 Windows XP SP2 和 Windows XP Professional x64 Edition 使用。Windows Vista 也将附带 PNRP 版本 2。从最简单的层次看,PNRP 本身就是一个采用 Windows 服务形式的 P2P 应用程序,并且 PNRP 节点的网格专用于发现加入到其他网格中的节点的物理地址。
PNRP 和 IPv6 PNRP 构建于 Internet 协议版本 6 (IPv6) 之上。由于 IPv6 对于多数开发人员而言还相当陌生,因此在讨论 PNRP 机制之前,非常有必要提及 IPv6 的至少一个重要方面。在 IPv6 中,地址是一个 128 位的值(这可能产生约 3.4×1038 种地址组合)。这种大小的 IPv6 地址池使 IPv6 的最重要功能之一 - 端对端寻址变为可能,即使这些地址被分割为多个子网并隐藏在 NAT 之后。
PNRP 示例 PNRP 功能的原型、结构、错误代码均在 Windows SDK 的 p2p.h 头文件中定义。如果某应用程序想要向 PNRP 注册一个网格名,它必须用非托管代码通过 Windows API 实现,或用托管代码通过公共语言运行库 (CLR) 的 P/Invoke 工具实现。目前,在 Windows API 的 PNRP 部分的 .NET Framework 中未包含托管包装。但您可以通过使用 netsh 命令行实用程序来访问 PRNP。通过 netsh,您可以按以下所示向 PNRP 注册一个新的 PNRP 名:
| c:\temp>netsh netsh>p2p pnrp peer netsh p2p pnrp peer>add 0.justinsmith Ok. |
| netsh p2p pnrp peer>resolve 0.justinsmith Resolve started... Found: Comment: gonzo Addresses: [0000:0000:0000:0000:0000:0000:0000:0001]:8350 udp 192.168.42.100:8350 tcp |
PeerChannel
Windows Communication Foundation 的主要优点之一就是,它为许多不同类型的分布式应用程序提供了一个通用的编程模型。例如,编写一个基于 TCP/IP 通过二进制编码消息进行通信的分布式应用程序所需的代码与编写一个基于 HTTP 通过符合 WS-* 的可互操作的消息进行通信的分布式应用程序所需的代码惊人地相似。Windows Communication Foundation 的一个鲜为人知的功能就是它支持使用这同一个通用编程模型来构建 P2P 应用程序。由于 Windows Communication Foundation 对 P2P 应用程序的支持,可能会有人将其视为一种网格技术,但实际上,只有 PeerChannel Windows Communication Foundation 模块才专用于构建 P2P 应用程序。因此,PeerChannel 这个术语通常用于指代 Windows Communication Foundation 的 P2P 功能。无论 Windows Communication Foundation 中的 PeerChannel 指代的是什么,它实际上消除了通常与 P2P 应用程序开发相伴的所有复杂性,并且在我看来,它是 P2P 应用程序开发领域的一个创新性突破。
PeerChannel 网格 PeerChannel 网格是专为消息扩散而设计。但 PeerChannel 包含了可将消息传播到网格的一部分而不是整个网格的机制。因此,更准确地说,PeerChannel 网格是专为多方消息传送而设计。
PeerChannel 网格的结构由每个节点所连接的邻居数量所控制。为此,PeerChannel 网格会主动维护网格的结构。这种维护的作用就是使网格性能稳健并且分布均匀。更具体点说,网格中的节点会设法将连接的邻居数保持在两到七个之间。这些阈值可使对本地节点的资源需求与保持网格稳健性之间取得平衡。
如果某节点在进入网格时带有三个邻居,然后其中两个邻居离开网格,则该节点将开始一个维护周期以试图获取新的邻居连接。同样,如果一个节点连接的邻居少于七个,则它将接受新连接,直到它具有七个邻居连接时为止。当一个 PeerChannel 节点连有三个邻居时,则认为它处于理想的连接状态,但一个节点将接受多达七个邻居,以便低于邻居数最低阈值的节点可以迅速获得新的邻居。应注意的是,您的应用程序代码不能更改这些阈值或对网格的维护实施任何控制,这一点很重要。这些细节问题完全由 PeerChannel 基础结构逐个节点地处理。
PeerChannel 提供了 PNRP 解析程序和自定义解析程序,以供用作预期节点发现网格中已有节点地址的方法。无论选择哪个解析方法,主旨都是一样的:将网格名传递到解析程序并接收网格中其他节点的 IP 地址列表。一旦解析进程生成地址列表,预期 PeerChannel 节点就并发连接到每个地址。当 PeerChannel 网格中已有的某节点收到其中一个连接请求时,它可以接受或拒绝该连接。如果接受该连接,则现有节点会向新连接的节点发送一条欢迎消息,消息中除了其他内容之外,还包含网格中其他节点的地址列表。如果拒绝该连接,则现有节点会向预期节点发送一条拒绝消息,消息中包含拒绝理由以及网格中其他节点的地址列表。
这里的重要一点是,网格名解析(通过 PNRP 解析程序或自定义解析程序执行)不是向 PeerChannel 中预期节点返回地址列表的唯一方式。与将网格名解析作为预期节点获取地址的唯一方法相比,此特性可使节点更快速地进入理想的连接状态。此外,这一特性使网格中的节点可对节点拥有的邻居数(这一因素会进而影响网格的稳健性)进行控制。
PeerChannel 网格内的通信被调整为尽量减少重复性的消息传递。当网格中的某节点向该网格发送消息时,实际上是在向其邻居发送消息。当收到消息后,每个邻居都会检验该消息,然后将其转发给自己的邻居。如果一个 PeerChannel 节点从某邻居收到消息,它不会将此消息转发回该邻居。此外,如果一个 PeerChannel 节点经常从某邻居那里收到先前已收到并处理过的消息,则与该邻居的连接可能会在下一个维护周期中终止。这些功能将通过每个节点上的本地高速缓存来实现。在内部,PeerChannel 网格中的每个节点都会对 WS-Addressing 消息 ID 的值和传送消息的邻居的标识符进行缓存处理。节点在决定向哪些邻居传送该消息时会检查这个高速缓存。将这些功能相结合后,会将网格调整为以最低的重复率和网络带宽消耗来向网格中的各节点传送消息。
如前所述,PeerChannel 节点还可以将消息发送给网格中节点的子集。这可以通过向消息分配一个跳跃计数来实现,这实际上是跟踪转发消息所经由的节点数的方式。不要将这种机制与定向消息传送相混淆,定向消息传送是将消息传送目标锁定在某个特定节点。更确切地说,跳跃计数是模糊界定接收消息的节点数的方式。例如,如果一个 PeerChannel 节点(节点 A)有三个邻居且在跳跃计数为 1 的情况下向网格发送一个消息,则该消息将被传送到三个节点。同样,如果节点 A 的每个邻居也都有三个唯一邻居且节点 A 在跳跃计数为 2 的情况下向网格发送一个消息,则该消息将被传送到九个节点。但如果节点 A 的任一邻居有共用的邻居,则此数字将相应减少。
从物理上说,跳跃计数在消息中被表示为标头块中的一个整数。当某节点收到带有跳跃计数的消息时,它会检查跳跃计数的值。如果该值大于零,节点会单调递减此跳跃计数,然后将带有递减后的跳跃计数值的消息转发给相应邻居。如果所接收消息中包含的跳跃计数为 0,则不转发该消息。另需注意的重要一点是,跳跃计数标头块被排除在消息签名之外,因此更改这个值不会影响到应用于消息的数字签名的完整性,而且会防止产生与重复生成数字签名并将其序列化到消息相应部分中所关联的开销。
PeerChannel 示例 让我们用 PeerChannel 和 Windows 窗体来构建一个简单的 P2P 应用程序,称之为 PictureViewer。顾名思义,该应用程序的用途是允许网格中的所有节点可以查看同一张图片。从高层次来说,构建此应用程序所需的步骤如下所示:
1.定义基本的 Windows 窗体样板代码。
2.向窗体添加控件。
3.定义必需的 Windows Communication Foundation 服务合约。
4.编写连接到网格和从网格接收消息所需的 Windows Communication Foundation 代码。
5.编写向网格中其他节点发送消息所需的代码。